diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000000..66b28b3485d8 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,32 @@ +# +# An auto defined `clippy` feature was introduced, +# but it was found to clash with user defined features, +# so was renamed to `cargo-clippy`. +# +# If you want standard clippy run: +# RUSTFLAGS= cargo clippy +[target.'cfg(feature = "cargo-clippy")'] +rustflags = [ + "-Aclippy::all", + "-Dclippy::correctness", + "-Aclippy::if-same-then-else", + "-Aclippy::clone-double-ref", + "-Dclippy::complexity", + "-Aclippy::zero-prefixed-literal", # 00_1000_000 + "-Aclippy::type_complexity", # raison d'etre + "-Aclippy::nonminimal-bool", # maybe + "-Aclippy::borrowed-box", # Reasonable to fix this one + "-Aclippy::too-many-arguments", # (Turning this on would lead to) + "-Aclippy::unnecessary_cast", # Types may change + "-Aclippy::identity-op", # One case where we do 0 + + "-Aclippy::useless_conversion", # Types may change + "-Aclippy::unit_arg", # styalistic. + "-Aclippy::option-map-unit-fn", # styalistic + "-Aclippy::bind_instead_of_map", # styalistic + "-Aclippy::erasing_op", # E.g. 0 * DOLLARS + "-Aclippy::eq_op", # In tests we test equality. + "-Aclippy::while_immutable_condition", # false positives + "-Aclippy::needless_option_as_deref", # false positives + "-Aclippy::derivable_impls", # false positives + "-Aclippy::stable_sort_primitive", # prefer stable sort +] diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b49246776c54..3fb899fd4366 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,7 +10,7 @@ updates: - dependency-name: "sp-*" - dependency-name: "frame-*" - dependency-name: "fork-tree" - - dependency-name: "remote-externalities" + - dependency-name: "frame-remote-externalities" - dependency-name: "pallet-*" - dependency-name: "beefy-*" - dependency-name: "try-runtime-*" diff --git a/.gitignore b/.gitignore index 5ea0458ddfc8..f9ab33eb63f3 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,4 @@ polkadot.* !polkadot.service !.rpm/* .DS_Store -.cargo .env diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0dd640186bb8..6d9300ba93a0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,13 +33,20 @@ variables: GIT_DEPTH: 100 CI_SERVER_NAME: "GitLab CI" CI_IMAGE: "paritytech/ci-linux:production" + BUILDAH_IMAGE: "quay.io/buildah/stable:v1.27" DOCKER_OS: "debian:stretch" ARCH: "x86_64" ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.2.78" - PIPELINE_SCRIPTS_TAG: "v0.4" default: cache: {} + retry: + max: 2 + when: + - runner_system_failure + - unknown_failure + - api_failure + interruptible: true .collect-artifacts: artifacts: @@ -61,6 +68,7 @@ default: # they will be used if the job fails .pipeline-stopper-vars: before_script: + - !reference [.job-switcher, before_script] - echo "FAILED_JOB_URL=${CI_JOB_URL}" > pipeline-stopper.env - echo "FAILED_JOB_NAME=${CI_JOB_NAME}" >> pipeline-stopper.env - echo "FAILED_JOB_NAME=${CI_JOB_NAME}" >> pipeline-stopper.env @@ -71,34 +79,29 @@ default: reports: dotenv: pipeline-stopper.env +.job-switcher: + before_script: + - if echo "$CI_DISABLED_JOBS" | grep -xF "$CI_JOB_NAME"; then echo "The job has been cancelled in CI settings"; exit 0; fi + .kubernetes-env: - retry: - max: 2 - when: - - runner_system_failure - - unknown_failure - - api_failure - interruptible: true + image: "${CI_IMAGE}" + before_script: + - !reference [.job-switcher, before_script] tags: - kubernetes-parity-build .docker-env: image: "${CI_IMAGE}" - retry: - max: 2 - when: - - runner_system_failure - - unknown_failure - - api_failure - interruptible: true + before_script: + - !reference [.job-switcher, before_script] tags: - - linux-docker + - linux-docker-vm-c2 .compiler-info: before_script: + - !reference [.job-switcher, before_script] - rustup show - cargo --version - - sccache -s .test-refs: rules: @@ -150,10 +153,8 @@ default: - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 .build-push-image: - extends: - - .kubernetes-env - image: quay.io/buildah/stable before_script: + - !reference [.job-switcher, before_script] - test -s ./artifacts/VERSION || exit 1 - test -s ./artifacts/EXTRATAG || exit 1 - VERSION="$(cat ./artifacts/VERSION)" @@ -196,8 +197,6 @@ include: # zombienet jobs - scripts/ci/gitlab/pipeline/zombienet.yml - - #### stage: .post deploy-parity-testnet: @@ -227,8 +226,23 @@ deploy-parity-testnet: PR_NUM: "${PR_NUM}" trigger: project: "parity/infrastructure/ci_cd/pipeline-stopper" + branch: "as-improve" + +remove-cancel-pipeline-message: + stage: .post + rules: + - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs + variables: + PROJECT_ID: "${CI_PROJECT_ID}" + PROJECT_NAME: "${CI_PROJECT_NAME}" + PIPELINE_ID: "${CI_PIPELINE_ID}" + FAILED_JOB_URL: "https://gitlab.com" + FAILED_JOB_NAME: "nope" + PR_NUM: "${CI_COMMIT_REF_NAME}" + trigger: + project: "parity/infrastructure/ci_cd/pipeline-stopper" -.cancel-pipeline-test-linux-stable: +cancel-pipeline-test-linux-stable: extends: .cancel-pipeline-template needs: - job: test-linux-stable diff --git a/Cargo.lock b/Cargo.lock index 5ce38b85f7a7..e9c3c297445b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,7 +42,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher", "cpufeatures", "opaque-debug 0.3.0", @@ -99,9 +99,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.51" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] name = "approx" @@ -130,15 +130,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -dependencies = [ - "nodrop", -] - [[package]] name = "arrayvec" version = "0.5.2" @@ -273,7 +264,7 @@ checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6" dependencies = [ "async-io", "blocking", - "cfg-if 1.0.0", + "cfg-if", "event-listener", "futures-lite", "libc", @@ -293,7 +284,6 @@ dependencies = [ "async-global-executor", "async-io", "async-lock", - "async-process", "crossbeam-utils", "futures-channel", "futures-core", @@ -310,21 +300,6 @@ dependencies = [ "wasm-bindgen-futures", ] -[[package]] -name = "async-std-resolver" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba50e24d9ee0a8950d3d03fc6d0dd10aa14b5de3b101949b4e160f7fee7c723" -dependencies = [ - "async-std", - "async-trait", - "futures-io", - "futures-util", - "pin-utils", - "socket2", - "trust-dns-resolver", -] - [[package]] name = "async-task" version = "4.0.3" @@ -333,9 +308,9 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "async-trait" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" +checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" dependencies = [ "proc-macro2", "quote", @@ -374,9 +349,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" @@ -386,7 +361,7 @@ checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object 0.27.1", @@ -435,11 +410,10 @@ dependencies = [ [[package]] name = "beefy-gadget" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "async-trait", - "beefy-primitives", "fnv", "futures", "futures-timer", @@ -458,6 +432,7 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-arithmetic", + "sp-beefy", "sp-blockchain", "sp-consensus", "sp-core", @@ -472,10 +447,9 @@ dependencies = [ [[package]] name = "beefy-gadget-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "beefy-gadget", - "beefy-primitives", "futures", "jsonrpsee", "log", @@ -484,6 +458,7 @@ dependencies = [ "sc-rpc", "sc-utils", "serde", + "sp-beefy", "sp-core", "sp-runtime", "thiserror", @@ -492,28 +467,11 @@ dependencies = [ [[package]] name = "beefy-merkle-tree" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "beefy-primitives", - "sp-api", - "sp-runtime", -] - -[[package]] -name = "beefy-primitives" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ - "parity-scale-codec", - "scale-info", - "serde", "sp-api", - "sp-application-crypto", - "sp-core", - "sp-io", - "sp-mmr-primitives", + "sp-beefy", "sp-runtime", - "sp-std", ] [[package]] @@ -571,16 +529,6 @@ dependencies = [ "digest 0.10.3", ] -[[package]] -name = "blake2-rfc" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -dependencies = [ - "arrayvec 0.4.12", - "constant_time_eq", -] - [[package]] name = "blake2b_simd" version = "1.0.0" @@ -612,7 +560,7 @@ dependencies = [ "arrayref", "arrayvec 0.7.2", "cc", - "cfg-if 1.0.0", + "cfg-if", "constant_time_eq", "digest 0.10.3", ] @@ -785,9 +733,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" dependencies = [ "jobserver", ] @@ -810,12 +758,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -830,11 +772,11 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chacha20" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" +checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher", "cpufeatures", "zeroize", @@ -842,9 +784,9 @@ dependencies = [ [[package]] name = "chacha20poly1305" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" +checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" dependencies = [ "aead", "chacha20", @@ -890,11 +832,11 @@ dependencies = [ [[package]] name = "ckb-merkle-mountain-range" -version = "0.3.2" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f061f97d64fd1822664bdfb722f7ae5469a97b77567390f7442be5b5dc82a5b" +checksum = "56ccb671c5921be8a84686e6212ca184cb1d7c51cadcdbfcbd1cc3f042f5dfb8" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", ] [[package]] @@ -957,6 +899,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "color-eyre" version = "0.6.1" @@ -992,9 +944,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" +checksum = "722e23542a15cea1f65d4a1419c4cfd7a26706c70871a13a04238ca3f40f1661" [[package]] name = "constant_time_eq" @@ -1039,7 +991,17 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "931ab2a3e6330a07900b8e7ca4e106cdcbb93f2b9a52df55e54ee53d8305b55d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", +] + +[[package]] +name = "cpu-time" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e393a7668fe1fad3075085b86c781883000b4ede868f43627b34a87c8b7ded" +dependencies = [ + "libc", + "winapi", ] [[package]] @@ -1155,7 +1117,7 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1164,7 +1126,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", ] @@ -1174,7 +1136,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] @@ -1185,7 +1147,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", "lazy_static", "memoffset", @@ -1198,7 +1160,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", ] @@ -1208,7 +1170,7 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ff1f980957787286a554052d03c7aee98d99cc32e09f6d45f0a814133c87978" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] @@ -1220,9 +1182,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.3.2" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" dependencies = [ "generic-array 0.14.4", "rand_core 0.6.3", @@ -1318,6 +1280,50 @@ dependencies = [ "zeroize", ] +[[package]] +name = "cxx" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "data-encoding" version = "2.3.2" @@ -1355,11 +1361,12 @@ dependencies = [ [[package]] name = "der" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +checksum = "13dd2ae565c0a381dde7fade45fce95984c568bdcb4700a4fdbe3175e0380b2f" dependencies = [ "const-oid", + "zeroize", ] [[package]] @@ -1442,7 +1449,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dirs-sys-next", ] @@ -1546,9 +1553,9 @@ checksum = "ee2626afccd7561a06cf1367e2950c4718ea04565e20fb5029b6c7d8ad09abcf" [[package]] name = "ecdsa" -version = "0.13.4" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0d69ae62e0ce582d56380743515fefaf1a8c70cec685d9677636d7e30ae9dc9" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" dependencies = [ "der", "elliptic-curve", @@ -1581,15 +1588,15 @@ dependencies = [ [[package]] name = "ed25519-zebra" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ "curve25519-dalek 3.2.0", + "hashbrown", "hex", "rand_core 0.6.3", "sha2 0.9.8", - "thiserror", "zeroize", ] @@ -1601,13 +1608,14 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "elliptic-curve" -version = "0.11.12" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b477563c2bfed38a3b7a60964c49e058b2510ad3f12ba3483fd8f62c2306d6" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" dependencies = [ "base16ct", "crypto-bigint", "der", + "digest 0.10.3", "ff", "generic-array 0.14.4", "group", @@ -1623,7 +1631,7 @@ version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1848,7 +1856,7 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc04871e5ae3aa2952d552dae6b291b3099723bf779a8054281c1366a54613ef" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "log", "serde", @@ -1860,9 +1868,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2958d04124b9f27f175eaeb9a9f383d026098aa837eadd8ba22c11f13a05b9e" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ "rand_core 0.6.3", "subtle", @@ -1884,7 +1892,7 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "windows-sys 0.36.1", @@ -1942,7 +1950,7 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crc32fast", "libc", "libz-sys", @@ -1982,7 +1990,7 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fork-tree" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", ] @@ -2006,7 +2014,7 @@ checksum = "85dcb89d2b10c5f6133de2efd8c11959ce9dbb46a2f7a4cab208c4eeda6ce1ab" [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -2029,7 +2037,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "Inflector", "array-bytes", @@ -2070,6 +2078,7 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-state-machine", + "sp-std", "sp-storage", "sp-trie", "tempfile", @@ -2080,7 +2089,7 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2091,7 +2100,7 @@ dependencies = [ [[package]] name = "frame-election-provider-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -2099,6 +2108,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-arithmetic", + "sp-core", "sp-npos-elections", "sp-runtime", "sp-std", @@ -2107,7 +2117,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -2127,16 +2137,35 @@ version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df6bb8542ef006ef0de09a5c4420787d79823c0ed7924225822362fd2bf2ff2d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "parity-scale-codec", "scale-info", "serde", ] +[[package]] +name = "frame-remote-externalities" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" +dependencies = [ + "env_logger 0.9.0", + "futures", + "log", + "parity-scale-codec", + "serde", + "serde_json", + "sp-core", + "sp-io", + "sp-runtime", + "sp-version", + "substrate-rpc-client", + "tokio", +] + [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "bitflags", "frame-metadata", @@ -2168,7 +2197,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "Inflector", "cfg-expr", @@ -2182,7 +2211,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", @@ -2194,7 +2223,7 @@ dependencies = [ [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "proc-macro2", "quote", @@ -2204,7 +2233,7 @@ dependencies = [ [[package]] name = "frame-support-test" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-support-test-pallet", @@ -2227,7 +2256,7 @@ dependencies = [ [[package]] name = "frame-support-test-pallet" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -2238,7 +2267,7 @@ dependencies = [ [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "log", @@ -2256,7 +2285,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -2271,7 +2300,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "sp-api", @@ -2280,7 +2309,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "parity-scale-codec", @@ -2451,7 +2480,7 @@ dependencies = [ [[package]] name = "generate-bags" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "chrono", "frame-election-provider-support", @@ -2498,7 +2527,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", @@ -2511,7 +2540,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi 0.10.0+wasi-snapshot-preview1", ] @@ -2584,9 +2613,9 @@ dependencies = [ [[package]] name = "group" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5ac374b108929de78460075f3dc439fa66df9d8fc77e8f12caa5165fcf0c89" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ "ff", "rand_core 0.6.3", @@ -2697,6 +2726,15 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.3", +] + [[package]] name = "hmac-drbg" version = "0.3.0" @@ -2716,7 +2754,7 @@ checksum = "848e9c511092e0daa0a35a63e8e6e475a3e8f870741448b9f6028d69b142f18e" dependencies = [ "arbitrary", "lazy_static", - "memmap2 0.5.0", + "memmap2", "rustc_version", ] @@ -2739,20 +2777,26 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa", ] [[package]] name = "http-body" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", "pin-project-lite 0.2.7", ] +[[package]] +name = "http-range-header" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + [[package]] name = "httparse" version = "1.6.0" @@ -2795,7 +2839,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.1", + "itoa", "pin-project-lite 0.2.7", "socket2", "tokio", @@ -2923,7 +2967,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -2982,15 +3026,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "jobserver" @@ -3012,24 +3050,23 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.15.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd0d559d5e679b1ab2f869b486a11182923863b1b3ee8b421763cdd707b783a" +checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" dependencies = [ "jsonrpsee-core", - "jsonrpsee-http-server", "jsonrpsee-proc-macros", + "jsonrpsee-server", "jsonrpsee-types", "jsonrpsee-ws-client", - "jsonrpsee-ws-server", "tracing", ] [[package]] name = "jsonrpsee-client-transport" -version = "0.15.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8752740ecd374bcbf8b69f3e80b0327942df76f793f8d4e60d3355650c31fb74" +checksum = "965de52763f2004bc91ac5bcec504192440f0b568a5d621c59d9dbd6f886c3fb" dependencies = [ "futures-util", "http", @@ -3048,9 +3085,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.15.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3dc3e9cf2ba50b7b1d7d76a667619f82846caa39e8e8daa8a4962d74acaddca" +checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" dependencies = [ "anyhow", "arrayvec 0.7.2", @@ -3061,10 +3098,8 @@ dependencies = [ "futures-timer", "futures-util", "globset", - "http", "hyper", "jsonrpsee-types", - "lazy_static", "parking_lot 0.12.1", "rand 0.8.5", "rustc-hash", @@ -3074,45 +3109,48 @@ dependencies = [ "thiserror", "tokio", "tracing", - "tracing-futures", - "unicase", ] [[package]] -name = "jsonrpsee-http-server" -version = "0.15.1" +name = "jsonrpsee-proc-macros" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" +dependencies = [ + "heck", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "jsonrpsee-server" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03802f0373a38c2420c70b5144742d800b509e2937edc4afb116434f07120117" +checksum = "1fb69dad85df79527c019659a992498d03f8495390496da2f07e6c24c2b356fc" dependencies = [ "futures-channel", "futures-util", + "http", "hyper", "jsonrpsee-core", "jsonrpsee-types", "serde", "serde_json", + "soketto", "tokio", + "tokio-stream", + "tokio-util 0.7.1", + "tower", "tracing", - "tracing-futures", -] - -[[package]] -name = "jsonrpsee-proc-macros" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd67957d4280217247588ac86614ead007b301ca2fa9f19c19f880a536f029e3" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", ] [[package]] name = "jsonrpsee-types" -version = "0.15.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e290bba767401b646812f608c099b922d8142603c9e73a50fb192d3ac86f4a0d" +checksum = "5bd522fe1ce3702fd94812965d7bb7a3364b1c9aba743944c5a00529aae80f8c" dependencies = [ "anyhow", "beef", @@ -3124,9 +3162,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.15.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee5feddd5188e62ac08fcf0e56478138e581509d4730f3f7be9b57dd402a4ff" +checksum = "0b83daeecfc6517cfe210df24e570fb06213533dfb990318fae781f4c7119dd9" dependencies = [ "http", "jsonrpsee-client-transport", @@ -3134,36 +3172,16 @@ dependencies = [ "jsonrpsee-types", ] -[[package]] -name = "jsonrpsee-ws-server" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d488ba74fb369e5ab68926feb75a483458b88e768d44319f37e4ecad283c7325" -dependencies = [ - "futures-channel", - "futures-util", - "http", - "jsonrpsee-core", - "jsonrpsee-types", - "serde_json", - "soketto", - "tokio", - "tokio-stream", - "tokio-util 0.7.1", - "tracing", - "tracing-futures", -] - [[package]] name = "k256" -version = "0.10.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", - "sec1", + "sha2 0.10.2", ] [[package]] @@ -3174,13 +3192,13 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" [[package]] name = "kusama-runtime" -version = "0.9.31" +version = "0.9.36" dependencies = [ - "beefy-primitives", "bitvec", "frame-benchmarking", "frame-election-provider-support", "frame-executive", + "frame-remote-externalities", "frame-support", "frame-system", "frame-system-benchmarking", @@ -3203,13 +3221,13 @@ dependencies = [ "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", - "pallet-gilt", "pallet-grandpa", "pallet-identity", "pallet-im-online", "pallet-indices", "pallet-membership", "pallet-multisig", + "pallet-nis", "pallet-nomination-pools", "pallet-nomination-pools-benchmarking", "pallet-nomination-pools-runtime-api", @@ -3225,7 +3243,6 @@ dependencies = [ "pallet-session-benchmarking", "pallet-society", "pallet-staking", - "pallet-staking-reward-fn", "pallet-timestamp", "pallet-tips", "pallet-transaction-payment", @@ -3240,7 +3257,6 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-parachains", - "remote-externalities", "rustc-hex", "scale-info", "separator", @@ -3251,6 +3267,7 @@ dependencies = [ "sp-api", "sp-arithmetic", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-consensus-babe", "sp-core", @@ -3279,7 +3296,7 @@ dependencies = [ [[package]] name = "kusama-runtime-constants" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "polkadot-primitives", @@ -3301,35 +3318,31 @@ dependencies = [ [[package]] name = "kvdb" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585089ceadba0197ffe9af6740ab350b325e3c1f5fccfbc3522e0250c750409b" +checksum = "e7d770dcb02bf6835887c3a979b5107a04ff4bbde97a5f0928d27404a155add9" dependencies = [ - "parity-util-mem", "smallvec", ] [[package]] name = "kvdb-memorydb" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40d109c87bfb7759edd2a49b2649c1afe25af785d930ad6a38479b4dc70dd873" +checksum = "bf7a85fe66f9ff9cd74e169fdd2c94c6e1e74c412c99a73b4df3200b5d3760b2" dependencies = [ "kvdb", - "parity-util-mem", "parking_lot 0.12.1", ] [[package]] name = "kvdb-rocksdb" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c076cc2cdbac89b9910c853a36c957d3862a779f31c2661174222cefb49ee597" +checksum = "2182b8219fee6bd83aacaab7344e840179ae079d5216aa4e249b4d704646a844" dependencies = [ "kvdb", - "log", "num_cpus", - "parity-util-mem", "parking_lot 0.12.1", "regex", "rocksdb", @@ -3338,9 +3351,9 @@ dependencies = [ [[package]] name = "kvdb-shared-tests" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de82a1adb7ade192c0090dd56d059a626191c0638c795eb68aff4b0bd2c1f9be" +checksum = "64d3b4e3e80c369f1b5364b6acdeba9b8a02285e91a5570f7c0404b7f9024541" dependencies = [ "kvdb", ] @@ -3381,7 +3394,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "winapi", ] @@ -3464,7 +3477,6 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2322c9fb40d99101def6a01612ee30500c89abbbecb6297b3cd252903a4c1720" dependencies = [ - "async-std-resolver", "futures", "libp2p-core", "log", @@ -3485,7 +3497,7 @@ dependencies = [ "libp2p-core", "libp2p-swarm", "log", - "lru 0.8.0", + "lru", "prost", "prost-build", "prost-codec", @@ -3528,7 +3540,6 @@ version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "761704e727f7d68d58d7bc2231eafae5fc1b9814de24290f126df09d4bd37a15" dependencies = [ - "async-io", "data-encoding", "dns-parser", "futures", @@ -3539,6 +3550,7 @@ dependencies = [ "rand 0.8.5", "smallvec", "socket2", + "tokio", "void", ] @@ -3667,7 +3679,6 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9839d96761491c6d3e238e70554b856956fca0ab60feb9de2cd08eed4473fa92" dependencies = [ - "async-io", "futures", "futures-timer", "if-watch", @@ -3675,6 +3686,7 @@ dependencies = [ "libp2p-core", "log", "socket2", + "tokio", ] [[package]] @@ -3799,6 +3811,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + [[package]] name = "linked-hash-map" version = "0.5.4" @@ -3845,25 +3866,16 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "serde", "value-bag", ] [[package]] name = "lru" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" -dependencies = [ - "hashbrown", -] - -[[package]] -name = "lru" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936d98d2ddd79c18641c6709e7bb09981449694e402d1a0f0f657ea8d61f4a51" +checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" dependencies = [ "hashbrown", ] @@ -3879,9 +3891,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.23.2" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac20ed6991e01bf6a2e68cc73df2b389707403662a8ba89f68511fb340f724c" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" dependencies = [ "libc", "lz4-sys", @@ -3889,9 +3901,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.2" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca79aa95d8b3226213ad454d328369853be3a1382d89532a854f4d69640acae" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" dependencies = [ "cc", "libc", @@ -3966,15 +3978,6 @@ dependencies = [ "rustix", ] -[[package]] -name = "memmap2" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4" -dependencies = [ - "libc", -] - [[package]] name = "memmap2" version = "0.5.0" @@ -3995,22 +3998,12 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac11bb793c28fa095b7554466f53b3a60a2cd002afdac01bcf135cbd73a269" +checksum = "5e0c7cba9ce19ac7ffd2053ac9f49843bbd3f4318feedfd74e85c19d5fb0ba66" dependencies = [ "hash-db", "hashbrown", - "parity-util-mem", -] - -[[package]] -name = "memory-lru" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce95ae042940bad7e312857b929ee3d11b8f799a80cb7b9c7ec5125516906395" -dependencies = [ - "lru 0.8.0", ] [[package]] @@ -4066,25 +4059,50 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", - "miow", - "ntapi", "wasi 0.11.0+wasi-snapshot-preview1", - "winapi", + "windows-sys 0.42.0", ] [[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +name = "mmr-gadget" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ - "winapi", + "futures", + "log", + "parity-scale-codec", + "sc-client-api", + "sc-offchain", + "sp-api", + "sp-beefy", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-io", + "sp-mmr-primitives", + "sp-runtime", +] + +[[package]] +name = "mmr-rpc" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" +dependencies = [ + "anyhow", + "jsonrpsee", + "parity-scale-codec", + "serde", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-mmr-primitives", + "sp-runtime", ] [[package]] @@ -4093,7 +4111,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2be9a9090bc1cac2930688fa9478092a64c6a92ddc6ae0692d46b37d9cab709" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "downcast", "fragile", "lazy_static", @@ -4108,7 +4126,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86d702a0530a0141cf4ed147cf5ec7be6f2c187d4e37fcbefc39cf34116bfe8f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "proc-macro2", "quote", "syn", @@ -4204,7 +4222,7 @@ dependencies = [ "matrixmultiply", "nalgebra-macros", "num-complex", - "num-rational 0.4.0", + "num-rational", "num-traits", "rand 0.8.5", "rand_distr", @@ -4330,7 +4348,7 @@ checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" dependencies = [ "bitflags", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "memoffset", ] @@ -4342,17 +4360,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" dependencies = [ "bitflags", - "cfg-if 1.0.0", + "cfg-if", "libc", "memoffset", ] -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -4376,26 +4388,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.3" @@ -4418,12 +4410,12 @@ dependencies = [ [[package]] name = "num-format" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" +checksum = "54b862ff8df690cf089058c98b183676a7ed0f974cc08b426800093227cbff3b" dependencies = [ - "arrayvec 0.4.12", - "itoa 0.4.8", + "arrayvec 0.7.2", + "itoa", ] [[package]] @@ -4438,24 +4430,12 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" -dependencies = [ - "autocfg", - "num-bigint 0.2.6", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", - "num-bigint 0.4.3", + "num-bigint", "num-integer", "num-traits", ] @@ -4526,7 +4506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" dependencies = [ "bitflags", - "cfg-if 1.0.0", + "cfg-if", "foreign-types", "libc", "once_cell", @@ -4617,13 +4597,14 @@ checksum = "20448fd678ec04e6ea15bbe0476874af65e98a01515d667aa49f1434dc44ebf4" [[package]] name = "pallet-assets" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", "scale-info", + "sp-core", "sp-runtime", "sp-std", ] @@ -4631,7 +4612,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -4647,7 +4628,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -4662,7 +4643,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -4686,7 +4667,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -4706,15 +4687,15 @@ dependencies = [ [[package]] name = "pallet-bags-list-remote-tests" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-election-provider-support", + "frame-remote-externalities", "frame-support", "frame-system", "log", "pallet-bags-list", "pallet-staking", - "remote-externalities", "sp-core", "sp-runtime", "sp-std", @@ -4725,7 +4706,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -4740,15 +4721,15 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ - "beefy-primitives", "frame-support", "frame-system", "pallet-session", "parity-scale-codec", "scale-info", "serde", + "sp-beefy", "sp-runtime", "sp-std", ] @@ -4756,11 +4737,10 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "beefy-merkle-tree", - "beefy-primitives", "frame-support", "frame-system", "log", @@ -4770,6 +4750,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", + "sp-beefy", "sp-core", "sp-io", "sp-runtime", @@ -4779,7 +4760,7 @@ dependencies = [ [[package]] name = "pallet-bounties" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -4797,7 +4778,7 @@ dependencies = [ [[package]] name = "pallet-child-bounties" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -4816,7 +4797,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -4833,7 +4814,7 @@ dependencies = [ [[package]] name = "pallet-conviction-voting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "assert_matches", "frame-benchmarking", @@ -4850,7 +4831,7 @@ dependencies = [ [[package]] name = "pallet-democracy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -4868,7 +4849,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -4892,7 +4873,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-support-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -4905,7 +4886,7 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -4923,16 +4904,13 @@ dependencies = [ [[package]] name = "pallet-fast-unstake" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-election-provider-support", "frame-support", "frame-system", "log", - "pallet-balances", - "pallet-staking", - "pallet-timestamp", "parity-scale-codec", "scale-info", "sp-io", @@ -4941,25 +4919,10 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-gilt" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", - "sp-arithmetic", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -4982,7 +4945,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "enumflags2", "frame-benchmarking", @@ -4998,7 +4961,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5018,7 +4981,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5035,7 +4998,7 @@ dependencies = [ [[package]] name = "pallet-membership" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5052,9 +5015,8 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ - "ckb-merkle-mountain-range", "frame-benchmarking", "frame-support", "frame-system", @@ -5068,32 +5030,33 @@ dependencies = [ ] [[package]] -name = "pallet-mmr-rpc" -version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +name = "pallet-multisig" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ - "jsonrpsee", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", "parity-scale-codec", - "serde", - "sp-api", - "sp-blockchain", - "sp-core", - "sp-mmr-primitives", + "scale-info", + "sp-io", "sp-runtime", + "sp-std", ] [[package]] -name = "pallet-multisig" +name = "pallet-nis" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "log", "parity-scale-codec", "scale-info", - "sp-io", + "sp-arithmetic", + "sp-core", "sp-runtime", "sp-std", ] @@ -5101,7 +5064,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" version = "1.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -5118,7 +5081,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-benchmarking" version = "1.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5138,7 +5101,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" version = "1.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "sp-api", @@ -5148,7 +5111,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -5165,7 +5128,7 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5188,7 +5151,7 @@ dependencies = [ [[package]] name = "pallet-preimage" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5205,7 +5168,7 @@ dependencies = [ [[package]] name = "pallet-proxy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5220,7 +5183,7 @@ dependencies = [ [[package]] name = "pallet-ranked-collective" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5238,7 +5201,7 @@ dependencies = [ [[package]] name = "pallet-recovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5253,12 +5216,13 @@ dependencies = [ [[package]] name = "pallet-referenda" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "assert_matches", "frame-benchmarking", "frame-support", "frame-system", + "log", "parity-scale-codec", "scale-info", "serde", @@ -5271,7 +5235,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5282,12 +5246,13 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", + "sp-weights", ] [[package]] name = "pallet-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -5308,7 +5273,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5324,7 +5289,7 @@ dependencies = [ [[package]] name = "pallet-society" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -5338,7 +5303,7 @@ dependencies = [ [[package]] name = "pallet-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5361,7 +5326,7 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -5372,16 +5337,33 @@ dependencies = [ [[package]] name = "pallet-staking-reward-fn" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "log", "sp-arithmetic", ] +[[package]] +name = "pallet-state-trie-migration" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-sudo" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -5395,7 +5377,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5413,7 +5395,7 @@ dependencies = [ [[package]] name = "pallet-tips" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5432,7 +5414,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-support", "frame-system", @@ -5448,7 +5430,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -5458,23 +5440,25 @@ dependencies = [ "sp-core", "sp-rpc", "sp-runtime", + "sp-weights", ] [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "sp-api", "sp-runtime", + "sp-weights", ] [[package]] name = "pallet-treasury" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5491,7 +5475,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5507,7 +5491,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5522,7 +5506,7 @@ dependencies = [ [[package]] name = "pallet-whitelist" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-benchmarking", "frame-support", @@ -5536,7 +5520,7 @@ dependencies = [ [[package]] name = "pallet-xcm" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "frame-system", @@ -5558,7 +5542,7 @@ dependencies = [ [[package]] name = "pallet-xcm-benchmarks" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-benchmarking", "frame-support", @@ -5583,19 +5567,19 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.3.16" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb474d0ed0836e185cb998a6b140ed1073d1fbf27d690ecf9ede8030289382c" +checksum = "3a7511a0bec4a336b5929999d02b560d2439c993cccf98c26481484e811adc43" dependencies = [ - "blake2-rfc", + "blake2", "crc32fast", "fs2", "hex", "libc", "log", "lz4", - "memmap2 0.2.3", - "parking_lot 0.11.2", + "memmap2", + "parking_lot 0.12.1", "rand 0.8.5", "snap", ] @@ -5623,53 +5607,15 @@ checksum = "9299338969a3d2f491d65f140b00ddec470858402f888af98e8642fb5e8965cd" dependencies = [ "proc-macro-crate", "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "parity-send-wrapper" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" - -[[package]] -name = "parity-util-mem" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d32c34f4f5ca7f9196001c0aba5a1f9a5a12382c8944b8b0f90233282d1e8f8" -dependencies = [ - "cfg-if 1.0.0", - "hashbrown", - "impl-trait-for-tuples", - "parity-util-mem-derive", - "parking_lot 0.12.1", - "primitive-types", - "smallvec", - "tikv-jemalloc-ctl", - "tikv-jemallocator", - "winapi", -] - -[[package]] -name = "parity-util-mem-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" -dependencies = [ - "proc-macro2", + "quote", "syn", - "synstructure", ] [[package]] -name = "parity-wasm" -version = "0.32.0" +name = "parity-send-wrapper" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ad52817c4d343339b3bc2e26861bd21478eda0b7509acf83505727000512ac" -dependencies = [ - "byteorder", -] +checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" [[package]] name = "parity-wasm" @@ -5710,7 +5656,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", "redox_syscall", @@ -5724,7 +5670,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", @@ -5860,13 +5806,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs8" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" dependencies = [ "der", "spki", - "zeroize", ] [[package]] @@ -5883,22 +5828,22 @@ checksum = "e8d0eef3571242013a0d5dc84861c3ae4a652e56e12adf8bdc26ff5f8cb34c94" [[package]] name = "polkadot" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_cmd", "color-eyre", "nix 0.24.1", - "parity-util-mem", "polkadot-cli", "polkadot-core-primitives", "substrate-rpc-client", "tempfile", + "tikv-jemallocator", "tokio", ] [[package]] name = "polkadot-approval-distribution" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "env_logger 0.9.0", @@ -5922,7 +5867,7 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "bitvec", @@ -5947,14 +5892,14 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "derive_more", "fatality", "futures", "futures-timer", - "lru 0.8.0", + "lru", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -5976,7 +5921,7 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "env_logger 0.9.0", @@ -5984,7 +5929,7 @@ dependencies = [ "futures", "futures-timer", "log", - "lru 0.8.0", + "lru", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6005,7 +5950,7 @@ dependencies = [ [[package]] name = "polkadot-cli" -version = "0.9.31" +version = "0.9.36" dependencies = [ "clap", "frame-benchmarking-cli", @@ -6018,12 +5963,13 @@ dependencies = [ "polkadot-service", "pyroscope", "sc-cli", + "sc-executor", "sc-service", "sc-sysinfo", "sc-tracing", "sp-core", + "sp-io", "sp-keyring", - "sp-trie", "substrate-build-script-utils", "thiserror", "try-runtime-cli", @@ -6031,13 +5977,14 @@ dependencies = [ [[package]] name = "polkadot-client" -version = "0.9.31" +version = "0.9.36" dependencies = [ - "beefy-primitives", + "async-trait", "frame-benchmarking", "frame-benchmarking-cli", "frame-system", "frame-system-rpc-runtime-api", + "futures", "kusama-runtime", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -6053,6 +6000,7 @@ dependencies = [ "sc-service", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-blockchain", "sp-consensus", @@ -6073,7 +6021,7 @@ dependencies = [ [[package]] name = "polkadot-collator-protocol" -version = "0.9.31" +version = "0.9.36" dependencies = [ "always-assert", "assert_matches", @@ -6102,10 +6050,9 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" -version = "0.9.31" +version = "0.9.36" dependencies = [ "parity-scale-codec", - "parity-util-mem", "scale-info", "sp-core", "sp-runtime", @@ -6114,7 +6061,7 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "async-trait", @@ -6124,7 +6071,7 @@ dependencies = [ "futures-timer", "indexmap", "lazy_static", - "lru 0.8.0", + "lru", "parity-scale-codec", "polkadot-erasure-coding", "polkadot-node-network-protocol", @@ -6146,7 +6093,7 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" -version = "0.9.31" +version = "0.9.36" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -6159,7 +6106,7 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "async-trait", @@ -6186,7 +6133,7 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" -version = "0.9.31" +version = "0.9.36" dependencies = [ "always-assert", "assert_matches", @@ -6215,7 +6162,7 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" -version = "0.9.31" +version = "0.9.36" dependencies = [ "futures", "parity-scale-codec", @@ -6234,7 +6181,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "async-trait", @@ -6244,7 +6191,7 @@ dependencies = [ "futures-timer", "kvdb", "kvdb-memorydb", - "lru 0.8.0", + "lru", "merlin", "parity-scale-codec", "parking_lot 0.12.1", @@ -6273,7 +6220,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "bitvec", @@ -6301,7 +6248,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "bitvec", @@ -6327,7 +6274,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" -version = "0.9.31" +version = "0.9.36" dependencies = [ "futures", "polkadot-node-subsystem", @@ -6343,11 +6290,12 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "async-trait", "futures", + "futures-timer", "parity-scale-codec", "polkadot-node-core-pvf", "polkadot-node-primitives", @@ -6365,7 +6313,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" -version = "0.9.31" +version = "0.9.36" dependencies = [ "futures", "maplit", @@ -6384,7 +6332,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "futures", @@ -6405,7 +6353,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "fatality", @@ -6413,7 +6361,7 @@ dependencies = [ "futures-timer", "kvdb", "kvdb-memorydb", - "lru 0.8.0", + "lru", "parity-scale-codec", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -6432,12 +6380,13 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" -version = "0.9.31" +version = "0.9.36" dependencies = [ "async-trait", "futures", "futures-timer", "polkadot-node-subsystem", + "polkadot-overseer", "polkadot-primitives", "sp-blockchain", "sp-inherents", @@ -6448,7 +6397,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" -version = "0.9.31" +version = "0.9.36" dependencies = [ "bitvec", "fatality", @@ -6469,12 +6418,13 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf" -version = "0.9.31" +version = "0.9.36" dependencies = [ "always-assert", "assert_matches", "async-process", "async-std", + "cpu-time", "futures", "futures-timer", "hex-literal", @@ -6503,7 +6453,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-checker" -version = "0.9.31" +version = "0.9.36" dependencies = [ "futures", "futures-timer", @@ -6526,11 +6476,10 @@ dependencies = [ [[package]] name = "polkadot-node-core-runtime-api" -version = "0.9.31" +version = "0.9.36" dependencies = [ "futures", - "memory-lru", - "parity-util-mem", + "lru", "polkadot-node-primitives", "polkadot-node-subsystem", "polkadot-node-subsystem-test-helpers", @@ -6548,9 +6497,8 @@ dependencies = [ [[package]] name = "polkadot-node-jaeger" -version = "0.9.31" +version = "0.9.36" dependencies = [ - "async-std", "lazy_static", "log", "mick-jaeger", @@ -6561,11 +6509,12 @@ dependencies = [ "sc-network", "sp-core", "thiserror", + "tokio", ] [[package]] name = "polkadot-node-metrics" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_cmd", "bs58", @@ -6593,7 +6542,7 @@ dependencies = [ [[package]] name = "polkadot-node-network-protocol" -version = "0.9.31" +version = "0.9.36" dependencies = [ "async-trait", "derive_more", @@ -6616,7 +6565,7 @@ dependencies = [ [[package]] name = "polkadot-node-primitives" -version = "0.9.31" +version = "0.9.36" dependencies = [ "bounded-vec", "futures", @@ -6638,7 +6587,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem" -version = "0.9.31" +version = "0.9.36" dependencies = [ "polkadot-node-jaeger", "polkadot-node-subsystem-types", @@ -6647,7 +6596,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-test-helpers" -version = "0.9.31" +version = "0.9.36" dependencies = [ "async-trait", "futures", @@ -6665,7 +6614,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" -version = "0.9.31" +version = "0.9.36" dependencies = [ "async-trait", "derive_more", @@ -6687,7 +6636,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "async-trait", @@ -6697,13 +6646,13 @@ dependencies = [ "futures", "itertools", "kvdb", + "kvdb-memorydb", "kvdb-shared-tests", "lazy_static", "log", - "lru 0.8.0", + "lru", "parity-db", "parity-scale-codec", - "parity-util-mem", "parking_lot 0.11.2", "pin-project", "polkadot-node-jaeger", @@ -6727,16 +6676,15 @@ dependencies = [ [[package]] name = "polkadot-overseer" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "async-trait", "femme", "futures", "futures-timer", - "lru 0.8.0", + "lru", "orchestra", - "parity-util-mem", "parking_lot 0.12.1", "polkadot-node-metrics", "polkadot-node-network-protocol", @@ -6748,17 +6696,17 @@ dependencies = [ "sc-client-api", "sp-api", "sp-core", + "tikv-jemalloc-ctl", "tracing-gum", ] [[package]] name = "polkadot-parachain" -version = "0.9.31" +version = "0.9.36" dependencies = [ "derive_more", "frame-support", "parity-scale-codec", - "parity-util-mem", "polkadot-core-primitives", "scale-info", "serde", @@ -6769,7 +6717,7 @@ dependencies = [ [[package]] name = "polkadot-performance-test" -version = "0.9.31" +version = "0.9.36" dependencies = [ "env_logger 0.9.0", "kusama-runtime", @@ -6783,13 +6731,11 @@ dependencies = [ [[package]] name = "polkadot-primitives" -version = "0.9.31" +version = "0.9.36" dependencies = [ "bitvec", - "frame-system", "hex-literal", "parity-scale-codec", - "parity-util-mem", "polkadot-core-primitives", "polkadot-parachain", "scale-info", @@ -6806,13 +6752,11 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-std", - "sp-trie", - "sp-version", ] [[package]] name = "polkadot-primitives-test-helpers" -version = "0.9.31" +version = "0.9.36" dependencies = [ "polkadot-primitives", "rand 0.8.5", @@ -6824,12 +6768,12 @@ dependencies = [ [[package]] name = "polkadot-rpc" -version = "0.9.31" +version = "0.9.36" dependencies = [ "beefy-gadget", "beefy-gadget-rpc", "jsonrpsee", - "pallet-mmr-rpc", + "mmr-rpc", "pallet-transaction-payment-rpc", "polkadot-primitives", "sc-chain-spec", @@ -6855,13 +6799,13 @@ dependencies = [ [[package]] name = "polkadot-runtime" -version = "0.9.31" +version = "0.9.36" dependencies = [ - "beefy-primitives", "bitvec", "frame-benchmarking", "frame-election-provider-support", "frame-executive", + "frame-remote-externalities", "frame-support", "frame-system", "frame-system-benchmarking", @@ -6913,7 +6857,6 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-constants", "polkadot-runtime-parachains", - "remote-externalities", "rustc-hex", "scale-info", "separator", @@ -6923,6 +6866,7 @@ dependencies = [ "smallvec", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-consensus-babe", "sp-core", @@ -6951,9 +6895,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" -version = "0.9.31" +version = "0.9.36" dependencies = [ - "beefy-primitives", "bitvec", "frame-benchmarking", "frame-election-provider-support", @@ -6972,6 +6915,7 @@ dependencies = [ "pallet-election-provider-multi-phase", "pallet-session", "pallet-staking", + "pallet-staking-reward-fn", "pallet-timestamp", "pallet-transaction-payment", "pallet-treasury", @@ -6987,6 +6931,7 @@ dependencies = [ "serde_json", "slot-range-helper", "sp-api", + "sp-beefy", "sp-core", "sp-inherents", "sp-io", @@ -7002,7 +6947,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-constants" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "polkadot-primitives", @@ -7015,7 +6960,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-metrics" -version = "0.9.31" +version = "0.9.36" dependencies = [ "bs58", "parity-scale-codec", @@ -7026,7 +6971,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "bitflags", @@ -7057,6 +7002,7 @@ dependencies = [ "sc-keystore", "scale-info", "serde", + "serde_json", "sp-api", "sp-application-crypto", "sp-core", @@ -7077,12 +7023,11 @@ dependencies = [ [[package]] name = "polkadot-service" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "async-trait", "beefy-gadget", - "beefy-primitives", "env_logger 0.9.0", "frame-support", "frame-system-rpc-runtime-api", @@ -7093,7 +7038,8 @@ dependencies = [ "kvdb", "kvdb-rocksdb", "log", - "lru 0.8.0", + "lru", + "mmr-gadget", "pallet-babe", "pallet-im-online", "pallet-staking", @@ -7162,6 +7108,7 @@ dependencies = [ "serde_json", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-blockchain", "sp-consensus", @@ -7171,6 +7118,7 @@ dependencies = [ "sp-inherents", "sp-io", "sp-keystore", + "sp-mmr-primitives", "sp-offchain", "sp-runtime", "sp-session", @@ -7189,7 +7137,7 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" -version = "0.9.31" +version = "0.9.36" dependencies = [ "arrayvec 0.5.2", "assert_matches", @@ -7220,7 +7168,7 @@ dependencies = [ [[package]] name = "polkadot-statement-table" -version = "0.9.31" +version = "0.9.36" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -7229,7 +7177,7 @@ dependencies = [ [[package]] name = "polkadot-test-client" -version = "0.9.31" +version = "0.9.36" dependencies = [ "futures", "parity-scale-codec", @@ -7255,7 +7203,7 @@ dependencies = [ [[package]] name = "polkadot-test-malus" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "async-trait", @@ -7263,7 +7211,6 @@ dependencies = [ "color-eyre", "futures", "futures-timer", - "parity-util-mem", "polkadot-cli", "polkadot-erasure-coding", "polkadot-node-core-backing", @@ -7284,9 +7231,8 @@ dependencies = [ [[package]] name = "polkadot-test-runtime" -version = "0.9.31" +version = "0.9.36" dependencies = [ - "beefy-primitives", "bitvec", "frame-election-provider-support", "frame-executive", @@ -7324,6 +7270,7 @@ dependencies = [ "smallvec", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-consensus-babe", "sp-core", @@ -7349,7 +7296,7 @@ dependencies = [ [[package]] name = "polkadot-test-service" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-benchmarking", "frame-system", @@ -7404,7 +7351,7 @@ dependencies = [ [[package]] name = "polkadot-voter-bags" -version = "0.9.31" +version = "0.9.36" dependencies = [ "clap", "generate-bags", @@ -7420,7 +7367,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "log", "wepoll-ffi", @@ -7444,7 +7391,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "opaque-debug 0.3.0", "universal-hash", @@ -7457,7 +7404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55f35f865aa964be21fcde114cbd1cfbd9bf8a471460ed965b0f84f96c711401" dependencies = [ "backtrace", - "cfg-if 1.0.0", + "cfg-if", "findshlibs", "lazy_static", "libc", @@ -7596,7 +7543,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f64969ffd5dd8f39bd57a68ac53c163a095ed9d0fb707146da1b27025a3504" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fnv", "lazy_static", "memchr", @@ -7611,7 +7558,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83cd1b99916654a69008fd66b4f9397fbe08e6e51dfe23d4417acf5d3b8cb87c" dependencies = [ "dtoa", - "itoa 1.0.1", + "itoa", "parking_lot 0.12.1", "prometheus-client-derive-text-encode", ] @@ -7961,9 +7908,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.5" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -7981,13 +7928,13 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "remote-ext-tests-bags-list" -version = "0.9.31" +version = "0.9.36" dependencies = [ "clap", "frame-system", @@ -8004,23 +7951,6 @@ dependencies = [ "westend-runtime-constants", ] -[[package]] -name = "remote-externalities" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "env_logger 0.9.0", - "log", - "parity-scale-codec", - "serde", - "serde_json", - "sp-core", - "sp-io", - "sp-runtime", - "sp-version", - "substrate-rpc-client", -] - [[package]] name = "remove_dir_all" version = "0.5.3" @@ -8079,12 +8009,12 @@ dependencies = [ [[package]] name = "rfc6979" -version = "0.1.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ef608575f6392792f9ecf7890c00086591d29a83910939d430753f7c050525" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" dependencies = [ "crypto-bigint", - "hmac 0.11.0", + "hmac 0.12.1", "zeroize", ] @@ -8115,10 +8045,9 @@ dependencies = [ [[package]] name = "rococo-runtime" -version = "0.9.31" +version = "0.9.36" dependencies = [ "beefy-merkle-tree", - "beefy-primitives", "frame-benchmarking", "frame-executive", "frame-support", @@ -8138,7 +8067,6 @@ dependencies = [ "pallet-collective", "pallet-democracy", "pallet-elections-phragmen", - "pallet-gilt", "pallet-grandpa", "pallet-identity", "pallet-im-online", @@ -8146,6 +8074,7 @@ dependencies = [ "pallet-membership", "pallet-mmr", "pallet-multisig", + "pallet-nis", "pallet-offences", "pallet-preimage", "pallet-proxy", @@ -8154,6 +8083,7 @@ dependencies = [ "pallet-session", "pallet-society", "pallet-staking", + "pallet-state-trie-migration", "pallet-sudo", "pallet-timestamp", "pallet-tips", @@ -8178,6 +8108,7 @@ dependencies = [ "smallvec", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-consensus-babe", "sp-core", @@ -8203,7 +8134,7 @@ dependencies = [ [[package]] name = "rococo-runtime-constants" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "polkadot-primitives", @@ -8348,7 +8279,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "log", "sp-core", @@ -8359,7 +8290,7 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "futures", @@ -8386,7 +8317,7 @@ dependencies = [ [[package]] name = "sc-basic-authorship" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "futures-timer", @@ -8409,7 +8340,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -8425,10 +8356,10 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "impl-trait-for-tuples", - "memmap2 0.5.0", + "memmap2", "parity-scale-codec", "sc-chain-spec-derive", "sc-network-common", @@ -8442,7 +8373,7 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -8453,7 +8384,7 @@ dependencies = [ [[package]] name = "sc-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "chrono", @@ -8493,7 +8424,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "fnv", "futures", @@ -8521,7 +8452,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "hash-db", "kvdb", @@ -8546,13 +8477,14 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "futures", "futures-timer", "libp2p", "log", + "mockall", "parking_lot 0.12.1", "sc-client-api", "sc-utils", @@ -8570,19 +8502,18 @@ dependencies = [ [[package]] name = "sc-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "fork-tree", "futures", "log", "merlin", - "num-bigint 0.2.6", - "num-rational 0.2.4", + "num-bigint", + "num-rational", "num-traits", "parity-scale-codec", "parking_lot 0.12.1", - "rand 0.7.3", "sc-client-api", "sc-consensus", "sc-consensus-epochs", @@ -8612,7 +8543,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "jsonrpsee", @@ -8634,7 +8565,7 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "fork-tree", "parity-scale-codec", @@ -8647,7 +8578,7 @@ dependencies = [ [[package]] name = "sc-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "futures", @@ -8671,10 +8602,9 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ - "lazy_static", - "lru 0.7.8", + "lru", "parity-scale-codec", "parking_lot 0.12.1", "sc-executor-common", @@ -8682,12 +8612,10 @@ dependencies = [ "sc-executor-wasmtime", "sp-api", "sp-core", - "sp-core-hashing-proc-macro", "sp-externalities", "sp-io", "sp-panic-handler", "sp-runtime-interface", - "sp-tasks", "sp-trie", "sp-version", "sp-wasm-interface", @@ -8698,13 +8626,10 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ - "environmental", - "parity-scale-codec", "sc-allocator", "sp-maybe-compressed-blob", - "sp-sandbox", "sp-wasm-interface", "thiserror", "wasm-instrument", @@ -8714,14 +8639,12 @@ dependencies = [ [[package]] name = "sc-executor-wasmi" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "log", - "parity-scale-codec", "sc-allocator", "sc-executor-common", "sp-runtime-interface", - "sp-sandbox", "sp-wasm-interface", "wasmi", ] @@ -8729,19 +8652,16 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "log", "once_cell", - "parity-scale-codec", - "parity-wasm 0.45.0", "rustix", "sc-allocator", "sc-executor-common", "sp-runtime-interface", - "sp-sandbox", "sp-wasm-interface", "wasmtime", ] @@ -8749,7 +8669,7 @@ dependencies = [ [[package]] name = "sc-finality-grandpa" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "ahash", "array-bytes", @@ -8790,7 +8710,7 @@ dependencies = [ [[package]] name = "sc-finality-grandpa-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "finality-grandpa", "futures", @@ -8811,13 +8731,12 @@ dependencies = [ [[package]] name = "sc-informant" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "ansi_term", "futures", "futures-timer", "log", - "parity-util-mem", "sc-client-api", "sc-network-common", "sc-transaction-pool-api", @@ -8828,7 +8747,7 @@ dependencies = [ [[package]] name = "sc-keystore" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "async-trait", @@ -8843,7 +8762,7 @@ dependencies = [ [[package]] name = "sc-network" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "async-trait", @@ -8861,7 +8780,7 @@ dependencies = [ "linked-hash-map", "linked_hash_set", "log", - "lru 0.7.8", + "lru", "parity-scale-codec", "parking_lot 0.12.1", "pin-project", @@ -8890,7 +8809,7 @@ dependencies = [ [[package]] name = "sc-network-bitswap" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "cid", "futures", @@ -8910,7 +8829,7 @@ dependencies = [ [[package]] name = "sc-network-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "bitflags", @@ -8936,14 +8855,14 @@ dependencies = [ [[package]] name = "sc-network-gossip" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "ahash", "futures", "futures-timer", "libp2p", "log", - "lru 0.7.8", + "lru", "sc-network-common", "sc-peerset", "sp-runtime", @@ -8954,7 +8873,7 @@ dependencies = [ [[package]] name = "sc-network-light" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "futures", @@ -8975,14 +8894,15 @@ dependencies = [ [[package]] name = "sc-network-sync" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", + "async-trait", "fork-tree", "futures", "libp2p", "log", - "lru 0.7.8", + "lru", "mockall", "parity-scale-codec", "prost", @@ -8999,13 +8919,14 @@ dependencies = [ "sp-core", "sp-finality-grandpa", "sp-runtime", + "substrate-prometheus-endpoint", "thiserror", ] [[package]] name = "sc-network-transactions" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "futures", @@ -9024,7 +8945,7 @@ dependencies = [ [[package]] name = "sc-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "bytes", @@ -9054,7 +8975,7 @@ dependencies = [ [[package]] name = "sc-peerset" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "libp2p", @@ -9067,7 +8988,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -9076,7 +8997,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "hash-db", @@ -9106,7 +9027,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "jsonrpsee", @@ -9129,20 +9050,23 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", + "http", "jsonrpsee", "log", "serde_json", "substrate-prometheus-endpoint", "tokio", + "tower", + "tower-http", ] [[package]] name = "sc-rpc-spec-v2" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "hex", @@ -9161,7 +9085,7 @@ dependencies = [ [[package]] name = "sc-service" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "directories", @@ -9172,7 +9096,6 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parity-util-mem", "parking_lot 0.12.1", "pin-project", "rand 0.7.3", @@ -9232,12 +9155,10 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "log", "parity-scale-codec", - "parity-util-mem", - "parity-util-mem-derive", "parking_lot 0.12.1", "sc-client-api", "sp-core", @@ -9246,7 +9167,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -9265,7 +9186,7 @@ dependencies = [ [[package]] name = "sc-sysinfo" version = "6.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "libc", @@ -9284,7 +9205,7 @@ dependencies = [ [[package]] name = "sc-telemetry" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "chrono", "futures", @@ -9302,7 +9223,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "ansi_term", "atty", @@ -9333,7 +9254,7 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -9344,7 +9265,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "futures", @@ -9352,7 +9273,6 @@ dependencies = [ "linked-hash-map", "log", "parity-scale-codec", - "parity-util-mem", "parking_lot 0.12.1", "sc-client-api", "sc-transaction-pool-api", @@ -9371,7 +9291,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "futures", @@ -9385,7 +9305,7 @@ dependencies = [ [[package]] name = "sc-utils" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "futures-timer", @@ -9402,7 +9322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c46be926081c9f4dd5dd9b6f1d3e3229f2360bc6502dd8836f84a93b7c75e99a" dependencies = [ "bitvec", - "cfg-if 1.0.0", + "cfg-if", "derive_more", "parity-scale-codec", "scale-info-derive", @@ -9455,6 +9375,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "sct" version = "0.7.0" @@ -9467,10 +9393,11 @@ dependencies = [ [[package]] name = "sec1" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08da66b8b0965a5555b6bd6639e68ccba85e1e2506f5fbb089e93f8a04e1a2d1" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" dependencies = [ + "base16ct", "der", "generic-array 0.14.4", "pkcs8", @@ -9593,7 +9520,7 @@ version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ - "itoa 1.0.1", + "itoa", "ryu", "serde", ] @@ -9614,7 +9541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.1", + "itoa", "ryu", "serde", ] @@ -9638,7 +9565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", @@ -9650,7 +9577,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.3", ] @@ -9674,7 +9601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", @@ -9686,7 +9613,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.3", ] @@ -9749,11 +9676,11 @@ dependencies = [ [[package]] name = "signature" -version = "1.4.0" +version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02658e48d89f2bec991f9a78e69cfa4c316f8d6a6c4ec12fae1aeb263d486788" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ - "digest 0.9.0", + "digest 0.10.3", "rand_core 0.6.3", ] @@ -9783,7 +9710,7 @@ checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" [[package]] name = "slot-range-helper" -version = "0.9.31" +version = "0.9.36" dependencies = [ "enumn", "parity-scale-codec", @@ -9850,6 +9777,7 @@ dependencies = [ "bytes", "flate2", "futures", + "http", "httparse", "log", "rand 0.8.5", @@ -9859,7 +9787,7 @@ dependencies = [ [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "hash-db", "log", @@ -9877,7 +9805,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "blake2", "proc-macro-crate", @@ -9888,8 +9816,8 @@ dependencies = [ [[package]] name = "sp-application-crypto" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "scale-info", @@ -9901,8 +9829,8 @@ dependencies = [ [[package]] name = "sp-arithmetic" -version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "integer-sqrt", "num-traits", @@ -9917,7 +9845,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "scale-info", @@ -9930,7 +9858,7 @@ dependencies = [ [[package]] name = "sp-authorship" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "parity-scale-codec", @@ -9939,10 +9867,27 @@ dependencies = [ "sp-std", ] +[[package]] +name = "sp-beefy" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-io", + "sp-mmr-primitives", + "sp-runtime", + "sp-std", +] + [[package]] name = "sp-block-builder" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "sp-api", @@ -9954,11 +9899,11 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "log", - "lru 0.7.8", + "lru", "parity-scale-codec", "parking_lot 0.12.1", "sp-api", @@ -9972,7 +9917,7 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "futures", @@ -9991,7 +9936,7 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "merlin", @@ -10014,7 +9959,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "scale-info", @@ -10028,7 +9973,7 @@ dependencies = [ [[package]] name = "sp-consensus-vrf" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "scale-info", @@ -10040,8 +9985,8 @@ dependencies = [ [[package]] name = "sp-core" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "base58", @@ -10060,7 +10005,6 @@ dependencies = [ "merlin", "num-traits", "parity-scale-codec", - "parity-util-mem", "parking_lot 0.12.1", "primitive-types", "rand 0.7.3", @@ -10086,8 +10030,8 @@ dependencies = [ [[package]] name = "sp-core-hashing" -version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "blake2", "byteorder", @@ -10101,7 +10045,7 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "proc-macro2", "quote", @@ -10112,7 +10056,7 @@ dependencies = [ [[package]] name = "sp-database" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "kvdb", "parking_lot 0.12.1", @@ -10120,8 +10064,8 @@ dependencies = [ [[package]] name = "sp-debug-derive" -version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "proc-macro2", "quote", @@ -10130,8 +10074,8 @@ dependencies = [ [[package]] name = "sp-externalities" -version = "0.12.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "environmental", "parity-scale-codec", @@ -10142,7 +10086,7 @@ dependencies = [ [[package]] name = "sp-finality-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "finality-grandpa", "log", @@ -10160,7 +10104,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -10173,10 +10117,11 @@ dependencies = [ [[package]] name = "sp-io" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "bytes", + "ed25519-dalek", "futures", "hash-db", "libsecp256k1", @@ -10199,8 +10144,8 @@ dependencies = [ [[package]] name = "sp-keyring" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "lazy_static", "sp-core", @@ -10210,8 +10155,8 @@ dependencies = [ [[package]] name = "sp-keystore" -version = "0.12.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "futures", @@ -10228,7 +10173,7 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "thiserror", "zstd", @@ -10237,8 +10182,9 @@ dependencies = [ [[package]] name = "sp-mmr-primitives" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ + "ckb-merkle-mountain-range", "log", "parity-scale-codec", "scale-info", @@ -10248,12 +10194,13 @@ dependencies = [ "sp-debug-derive", "sp-runtime", "sp-std", + "thiserror", ] [[package]] name = "sp-npos-elections" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "scale-info", @@ -10267,7 +10214,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "sp-api", "sp-core", @@ -10276,8 +10223,8 @@ dependencies = [ [[package]] name = "sp-panic-handler" -version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "backtrace", "lazy_static", @@ -10287,7 +10234,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "rustc-hash", "serde", @@ -10296,15 +10243,14 @@ dependencies = [ [[package]] name = "sp-runtime" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "either", "hash256-std-hasher", "impl-trait-for-tuples", "log", "parity-scale-codec", - "parity-util-mem", "paste", "rand 0.7.3", "scale-info", @@ -10319,8 +10265,8 @@ dependencies = [ [[package]] name = "sp-runtime-interface" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -10337,8 +10283,8 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" -version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "Inflector", "proc-macro-crate", @@ -10347,24 +10293,10 @@ dependencies = [ "syn", ] -[[package]] -name = "sp-sandbox" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "log", - "parity-scale-codec", - "sp-core", - "sp-io", - "sp-std", - "sp-wasm-interface", - "wasmi", -] - [[package]] name = "sp-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "scale-info", @@ -10378,18 +10310,19 @@ dependencies = [ [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "scale-info", + "sp-core", "sp-runtime", "sp-std", ] [[package]] name = "sp-state-machine" -version = "0.12.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "hash-db", "log", @@ -10410,13 +10343,13 @@ dependencies = [ [[package]] name = "sp-std" -version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" [[package]] name = "sp-storage" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "impl-serde", "parity-scale-codec", @@ -10426,23 +10359,10 @@ dependencies = [ "sp-std", ] -[[package]] -name = "sp-tasks" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "log", - "sp-core", - "sp-externalities", - "sp-io", - "sp-runtime-interface", - "sp-std", -] - [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "futures-timer", @@ -10457,8 +10377,8 @@ dependencies = [ [[package]] name = "sp-tracing" -version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "sp-std", @@ -10470,7 +10390,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "sp-api", "sp-runtime", @@ -10479,7 +10399,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "log", @@ -10494,14 +10414,14 @@ dependencies = [ [[package]] name = "sp-trie" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "ahash", "hash-db", "hashbrown", "lazy_static", - "lru 0.7.8", + "lru", "memory-db", "nohash-hasher", "parity-scale-codec", @@ -10518,11 +10438,11 @@ dependencies = [ [[package]] name = "sp-version" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "impl-serde", "parity-scale-codec", - "parity-wasm 0.45.0", + "parity-wasm", "scale-info", "serde", "sp-core-hashing-proc-macro", @@ -10535,7 +10455,7 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "parity-scale-codec", "proc-macro2", @@ -10545,8 +10465,8 @@ dependencies = [ [[package]] name = "sp-wasm-interface" -version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "impl-trait-for-tuples", "log", @@ -10559,7 +10479,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", @@ -10580,9 +10500,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spki" -version = "0.5.4" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" dependencies = [ "base64ct", "der", @@ -10590,9 +10510,9 @@ dependencies = [ [[package]] name = "ss58-registry" -version = "1.29.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0837b5d62f42082c9d56cd946495ae273a3c68083b637b9153341d5e465146d" +checksum = "23d92659e7d18d82b803824a9ba5a6022cff101c3491d027c1c1d8d30e749284" dependencies = [ "Inflector", "num-format", @@ -10611,12 +10531,13 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "staking-miner" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_cmd", "clap", "exitcode", "frame-election-provider-support", + "frame-remote-externalities", "frame-support", "frame-system", "futures-util", @@ -10632,7 +10553,6 @@ dependencies = [ "polkadot-core-primitives", "polkadot-runtime", "polkadot-runtime-common", - "remote-externalities", "sc-transaction-pool-api", "serde", "serde_json", @@ -10774,7 +10694,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "platforms", ] @@ -10782,7 +10702,7 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "frame-system-rpc-runtime-api", "futures", @@ -10803,7 +10723,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures-util", "hyper", @@ -10816,7 +10736,7 @@ dependencies = [ [[package]] name = "substrate-rpc-client" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "async-trait", "jsonrpsee", @@ -10829,7 +10749,7 @@ dependencies = [ [[package]] name = "substrate-state-trie-migration-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "jsonrpsee", "log", @@ -10850,7 +10770,7 @@ dependencies = [ [[package]] name = "substrate-test-client" version = "2.0.1" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "array-bytes", "async-trait", @@ -10876,7 +10796,7 @@ dependencies = [ [[package]] name = "substrate-test-utils" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "futures", "substrate-test-utils-derive", @@ -10886,7 +10806,7 @@ dependencies = [ [[package]] name = "substrate-test-utils-derive" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -10897,7 +10817,7 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "ansi_term", "build-helper", @@ -10908,7 +10828,7 @@ dependencies = [ "tempfile", "toml", "walkdir", - "wasm-gc-api", + "wasm-opt", ] [[package]] @@ -10933,7 +10853,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e92a52f07eed9afba3d6f883652cde7cd75fcf327dd44e84f210958379158737" dependencies = [ "debugid", - "memmap2 0.5.0", + "memmap2", "stable_deref_trait", "uuid", ] @@ -11011,7 +10931,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "libc", "redox_syscall", @@ -11036,7 +10956,7 @@ checksum = "13a4ec180a2de59b57434704ccfad967f789b12737738798fa08798cd5824c16" [[package]] name = "test-parachain-adder" -version = "0.9.31" +version = "0.9.36" dependencies = [ "dlmalloc", "parity-scale-codec", @@ -11049,7 +10969,7 @@ dependencies = [ [[package]] name = "test-parachain-adder-collator" -version = "0.9.31" +version = "0.9.36" dependencies = [ "clap", "futures", @@ -11075,14 +10995,14 @@ dependencies = [ [[package]] name = "test-parachain-halt" -version = "0.9.31" +version = "0.9.36" dependencies = [ "substrate-wasm-builder", ] [[package]] name = "test-parachain-undying" -version = "0.9.31" +version = "0.9.36" dependencies = [ "dlmalloc", "log", @@ -11096,7 +11016,7 @@ dependencies = [ [[package]] name = "test-parachain-undying-collator" -version = "0.9.31" +version = "0.9.36" dependencies = [ "clap", "futures", @@ -11122,7 +11042,7 @@ dependencies = [ [[package]] name = "test-parachains" -version = "0.9.31" +version = "0.9.36" dependencies = [ "parity-scale-codec", "sp-core", @@ -11133,7 +11053,7 @@ dependencies = [ [[package]] name = "test-runtime-constants" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "polkadot-primitives", @@ -11146,18 +11066,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -11289,16 +11209,16 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.2" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" dependencies = [ + "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", - "once_cell", "parking_lot 0.12.1", "pin-project-lite 0.2.7", "signal-hook-registry", @@ -11399,6 +11319,41 @@ dependencies = [ "serde", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite 0.2.7", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.1" @@ -11411,7 +11366,8 @@ version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "log", "pin-project-lite 0.2.7", "tracing-attributes", "tracing-core", @@ -11450,7 +11406,7 @@ dependencies = [ [[package]] name = "tracing-gum" -version = "0.9.31" +version = "0.9.36" dependencies = [ "polkadot-node-jaeger", "polkadot-primitives", @@ -11460,7 +11416,7 @@ dependencies = [ [[package]] name = "tracing-gum-proc-macro" -version = "0.9.31" +version = "0.9.36" dependencies = [ "assert_matches", "expander 0.0.6", @@ -11561,7 +11517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" dependencies = [ "async-trait", - "cfg-if 1.0.0", + "cfg-if", "data-encoding", "enum-as-inner", "futures-channel", @@ -11574,6 +11530,7 @@ dependencies = [ "smallvec", "thiserror", "tinyvec", + "tokio", "tracing", "url", ] @@ -11584,7 +11541,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "futures-util", "ipconfig", "lazy_static", @@ -11593,6 +11550,7 @@ dependencies = [ "resolv-conf", "smallvec", "thiserror", + "tokio", "tracing", "trust-dns-proto", ] @@ -11606,22 +11564,26 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "try-runtime-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.36#cb4f2491b00af7d7817f3a54209c26b20faa1f51" dependencies = [ "clap", + "frame-remote-externalities", "frame-try-runtime", + "hex", "log", "parity-scale-codec", - "remote-externalities", "sc-chain-spec", "sc-cli", "sc-executor", "sc-service", "serde", + "sp-api", "sp-core", + "sp-debug-derive", "sp-externalities", "sp-io", "sp-keystore", + "sp-rpc", "sp-runtime", "sp-state-machine", "sp-version", @@ -11677,7 +11639,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "digest 0.10.3", "rand 0.8.5", "static_assertions", @@ -11707,15 +11669,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.7" @@ -11899,7 +11852,7 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "serde", "serde_json", "wasm-bindgen-macro", @@ -11926,7 +11879,7 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -11962,23 +11915,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] -name = "wasm-gc-api" -version = "0.1.11" +name = "wasm-instrument" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c32691b6c7e6c14e7f8fd55361a9088b507aa49620fcd06c09b3a1082186b9" +checksum = "aa1dafb3e60065305741e83db35c6c2584bb3725b692b5b66148a38d72ace6cd" dependencies = [ - "log", - "parity-wasm 0.32.0", - "rustc-demangle", + "parity-wasm", ] [[package]] -name = "wasm-instrument" -version = "0.3.0" +name = "wasm-opt" +version = "0.110.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa1dafb3e60065305741e83db35c6c2584bb3725b692b5b66148a38d72ace6cd" +checksum = "b68e8037b4daf711393f4be2056246d12d975651b14d581520ad5d1f19219cec" +dependencies = [ + "anyhow", + "libc", + "strum", + "strum_macros", + "tempfile", + "thiserror", + "wasm-opt-cxx-sys", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-cxx-sys" +version = "0.110.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91adbad477e97bba3fbd21dd7bfb594e7ad5ceb9169ab1c93ab9cb0ada636b6f" +dependencies = [ + "anyhow", + "cxx", + "cxx-build", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-sys" +version = "0.110.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec4fa5a322a4e6ac22fd141f498d56afbdbf9df5debeac32380d2dcaa3e06941" dependencies = [ - "parity-wasm 0.45.0", + "anyhow", + "cc", + "cxx", + "cxx-build", + "regex", ] [[package]] @@ -12002,7 +11985,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc13b3c219ca9aafeec59150d80d89851df02e0061bc357b4d66fc55a8d38787" dependencies = [ - "parity-wasm 0.45.0", + "parity-wasm", "wasmi-validation", "wasmi_core", ] @@ -12013,7 +11996,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ff416ad1ff0c42e5a926ed5d5fab74c0f098749aa0ad8b2a34b982ce0e867b" dependencies = [ - "parity-wasm 0.45.0", + "parity-wasm", ] [[package]] @@ -12025,7 +12008,7 @@ dependencies = [ "downcast-rs", "libm", "memory_units", - "num-rational 0.4.0", + "num-rational", "num-traits", ] @@ -12046,7 +12029,7 @@ checksum = "8a10dc9784d8c3a33c970e3939180424955f08af2e7f20368ec02685a0e8f065" dependencies = [ "anyhow", "bincode", - "cfg-if 1.0.0", + "cfg-if", "indexmap", "libc", "log", @@ -12072,7 +12055,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee4dbdc6daf68528cad1275ac91e3f51848ce9824385facc94c759f529decdf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -12144,7 +12127,7 @@ dependencies = [ "addr2line", "anyhow", "bincode", - "cfg-if 1.0.0", + "cfg-if", "cpp_demangle", "gimli", "log", @@ -12179,7 +12162,7 @@ checksum = "ae79e0515160bd5abee5df50a16c4eb8db9f71b530fc988ae1d9ce34dcb8dd01" dependencies = [ "anyhow", "cc", - "cfg-if 1.0.0", + "cfg-if", "indexmap", "libc", "log", @@ -12248,13 +12231,13 @@ dependencies = [ [[package]] name = "westend-runtime" -version = "0.9.31" +version = "0.9.36" dependencies = [ - "beefy-primitives", "bitvec", "frame-benchmarking", "frame-election-provider-support", "frame-executive", + "frame-remote-externalities", "frame-support", "frame-system", "frame-system-benchmarking", @@ -12307,7 +12290,6 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "polkadot-runtime-parachains", - "remote-externalities", "rustc-hex", "scale-info", "serde", @@ -12316,6 +12298,7 @@ dependencies = [ "smallvec", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-consensus-babe", "sp-core", @@ -12344,7 +12327,7 @@ dependencies = [ [[package]] name = "westend-runtime-constants" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "polkadot-primitives", @@ -12442,6 +12425,27 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.32.0" @@ -12460,6 +12464,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.32.0" @@ -12478,6 +12488,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.32.0" @@ -12496,6 +12512,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.32.0" @@ -12514,6 +12536,18 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.32.0" @@ -12532,6 +12566,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "winreg" version = "0.7.0" @@ -12572,7 +12612,7 @@ dependencies = [ [[package]] name = "xcm" -version = "0.9.31" +version = "0.9.36" dependencies = [ "derivative", "impl-trait-for-tuples", @@ -12585,7 +12625,7 @@ dependencies = [ [[package]] name = "xcm-builder" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "frame-system", @@ -12608,7 +12648,7 @@ dependencies = [ [[package]] name = "xcm-executor" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-benchmarking", "frame-support", @@ -12625,7 +12665,7 @@ dependencies = [ [[package]] name = "xcm-executor-integration-tests" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "frame-system", @@ -12645,7 +12685,7 @@ dependencies = [ [[package]] name = "xcm-procedural" -version = "0.9.31" +version = "0.9.36" dependencies = [ "Inflector", "proc-macro2", @@ -12655,7 +12695,7 @@ dependencies = [ [[package]] name = "xcm-simulator" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "parity-scale-codec", @@ -12671,7 +12711,7 @@ dependencies = [ [[package]] name = "xcm-simulator-example" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "frame-system", @@ -12694,7 +12734,7 @@ dependencies = [ [[package]] name = "xcm-simulator-fuzzer" -version = "0.9.31" +version = "0.9.36" dependencies = [ "frame-support", "frame-system", @@ -12732,9 +12772,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.4.3" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" dependencies = [ "zeroize_derive", ] @@ -12753,7 +12793,7 @@ dependencies = [ [[package]] name = "zombienet-backchannel" -version = "0.9.31" +version = "0.9.36" dependencies = [ "futures-util", "lazy_static", diff --git a/Cargo.toml b/Cargo.toml index 450cc0f2d1da..bb0470e8d00d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,25 +6,31 @@ path = "src/main.rs" name = "polkadot" description = "Implementation of a `https://polkadot.network` node in Rust based on the Substrate framework." license = "GPL-3.0-only" -version = "0.9.31" +rust-version = "1.64.0" # workspace properties +readme = "README.md" +authors.workspace = true +edition.workspace = true +version.workspace = true + +[workspace.package] authors = ["Parity Technologies "] edition = "2021" -rust-version = "1.57.0" # custom profiles -readme = "README.md" +repository = "https://github.com/paritytech/polkadot.git" +version = "0.9.36" [dependencies] polkadot-cli = { path = "cli", features = [ "kusama-native", "westend-native", "rococo-native" ] } color-eyre = { version = "0.6.1", default-features = false } -parity-util-mem = { version = "0.12.0", default-features = false, features = ["jemalloc-global"] } +tikv-jemallocator = "0.5.0" [dev-dependencies] assert_cmd = "2.0.4" nix = "0.24.1" tempfile = "3.2.0" -tokio = "1.19.2" -substrate-rpc-client = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +tokio = "1.22.0" +substrate-rpc-client = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-core-primitives = { path = "core-primitives" } - + [workspace] members = [ "cli", @@ -126,7 +132,6 @@ maintenance = { status = "actively-developed" } # This list is ordered alphabetically. [profile.dev.package] blake2 = { opt-level = 3 } -blake2-rfc = { opt-level = 3 } blake2b_simd = { opt-level = 3 } chacha20poly1305 = { opt-level = 3 } cranelift-codegen = { opt-level = 3 } diff --git a/README.md b/README.md index 55b66f6ea619..319e1714fd7b 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,7 @@ cargo build # Builds all native code You can run the tests if you like: ```bash -cargo test --all --release +cargo test --workspace --release ``` You can start a development chain with: diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 8fc390e3932a..e84e25c18176 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "polkadot-cli" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Polkadot Relay-chain Client Node" -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [package.metadata.wasm-pack.profile.release] # `wasm-opt` has some problems on Linux, see @@ -25,26 +25,23 @@ polkadot-client = { path = "../node/client", optional = true } polkadot-node-core-pvf = { path = "../node/core/pvf", optional = true } polkadot-performance-test = { path = "../node/test/performance-test", optional = true } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.31" } -try-runtime-cli = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.31" } -sc-cli = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.31" } -sc-service = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.36" } +try-runtime-cli = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.36" } +sc-cli = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.36" } polkadot-node-metrics = { path = "../node/metrics" } -sc-tracing = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.31" } -sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } - -# this crate is used only to enable `trie-memory-tracker` feature -# see https://github.com/paritytech/substrate/pull/6745 -sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sc-tracing = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.36" } +sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [build-dependencies] -substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] -default = ["wasmtime", "db", "cli", "hostperfcheck", "full-node", "trie-memory-tracker", "polkadot-native"] -wasmtime = ["sc-cli/wasmtime"] +default = ["db", "cli", "hostperfcheck", "full-node", "polkadot-native"] db = ["service/db"] cli = [ "clap", @@ -61,9 +58,8 @@ runtime-benchmarks = [ "polkadot-node-metrics/runtime-benchmarks", "polkadot-performance-test?/runtime-benchmarks" ] -trie-memory-tracker = ["sp-trie/memory-tracker"] full-node = ["service/full-node"] -try-runtime = ["service/try-runtime"] +try-runtime = ["service/try-runtime", "try-runtime-cli/try-runtime"] fast-runtime = ["service/fast-runtime"] pyroscope = ["pyro"] hostperfcheck = ["polkadot-performance-test"] diff --git a/cli/src/command.rs b/cli/src/command.rs index 5ce7c05162c1..81d707e58a24 100644 --- a/cli/src/command.rs +++ b/cli/src/command.rs @@ -591,27 +591,27 @@ pub fn run() -> Result<()> { #[cfg(feature = "kusama-native")] if chain_spec.is_kusama() { - return Ok(runner.sync_run(|config| { + return runner.sync_run(|config| { cmd.run::(config) .map_err(|e| Error::SubstrateCli(e)) - })?) + }) } #[cfg(feature = "westend-native")] if chain_spec.is_westend() { - return Ok(runner.sync_run(|config| { + return runner.sync_run(|config| { cmd.run::(config) .map_err(|e| Error::SubstrateCli(e)) - })?) + }) } // else we assume it is polkadot. #[cfg(feature = "polkadot-native")] { - return Ok(runner.sync_run(|config| { + return runner.sync_run(|config| { cmd.run::(config) .map_err(|e| Error::SubstrateCli(e)) - })?) + }) } #[cfg(not(feature = "polkadot-native"))] @@ -638,9 +638,14 @@ pub fn run() -> Result<()> { Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?), #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { + use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, NativeExecutionDispatch}; let runner = cli.create_runner(cmd)?; let chain_spec = &runner.config().chain_spec; set_default_ss58_version(chain_spec); + type HostFunctionsOf = ExtendedHostFunctions< + sp_io::SubstrateHostFunctions, + ::ExtendHostFunctions, + >; use sc_service::TaskManager; let registry = &runner.config().prometheus_config.as_ref().map(|cfg| &cfg.registry); @@ -651,10 +656,9 @@ pub fn run() -> Result<()> { #[cfg(feature = "kusama-native")] if chain_spec.is_kusama() { - return runner.async_run(|config| { + return runner.async_run(|_| { Ok(( - cmd.run::( - config, + cmd.run::>( ) .map_err(Error::SubstrateCli), task_manager, @@ -664,10 +668,9 @@ pub fn run() -> Result<()> { #[cfg(feature = "westend-native")] if chain_spec.is_westend() { - return runner.async_run(|config| { + return runner.async_run(|_| { Ok(( - cmd.run::( - config, + cmd.run::>( ) .map_err(Error::SubstrateCli), task_manager, @@ -677,10 +680,9 @@ pub fn run() -> Result<()> { // else we assume it is polkadot. #[cfg(feature = "polkadot-native")] { - return runner.async_run(|config| { + return runner.async_run(|_| { Ok(( - cmd.run::( - config, + cmd.run::>( ) .map_err(Error::SubstrateCli), task_manager, diff --git a/core-primitives/Cargo.toml b/core-primitives/Cargo.toml index e3eea6a3f424..25939a245a09 100644 --- a/core-primitives/Cargo.toml +++ b/core-primitives/Cargo.toml @@ -1,16 +1,15 @@ [package] name = "polkadot-core-primitives" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } parity-scale-codec = { version = "3.1.5", default-features = false, features = [ "derive" ] } -parity-util-mem = { version = "0.12.0", default-features = false, optional = true } [features] default = [ "std" ] @@ -21,5 +20,4 @@ std = [ "sp-std/std", "scale-info/std", "parity-scale-codec/std", - "parity-util-mem", ] diff --git a/core-primitives/src/lib.rs b/core-primitives/src/lib.rs index bd0256dc7c9e..ca4d2372db38 100644 --- a/core-primitives/src/lib.rs +++ b/core-primitives/src/lib.rs @@ -21,8 +21,6 @@ //! These core Polkadot types are used by the relay chain and the Parachains. use parity_scale_codec::{Decode, Encode}; -#[cfg(feature = "std")] -use parity_util_mem::MallocSizeOf; use scale_info::TypeInfo; use sp_runtime::{ generic, @@ -66,7 +64,6 @@ pub type Hash = sp_core::H256; /// /// This type makes it easy to enforce that a hash is a candidate hash on the type level. #[derive(Clone, Copy, Encode, Decode, Hash, Eq, PartialEq, Default, PartialOrd, Ord, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct CandidateHash(pub Hash); #[cfg(feature = "std")] @@ -127,7 +124,6 @@ pub type DownwardMessage = sp_std::vec::Vec; /// A wrapped version of `DownwardMessage`. The difference is that it has attached the block number when /// the message was sent. #[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct InboundDownwardMessage { /// The block number at which these messages were put into the downward message queue. pub sent_at: BlockNumber, @@ -137,7 +133,6 @@ pub struct InboundDownwardMessage { /// An HRMP message seen from the perspective of a recipient. #[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct InboundHrmpMessage { /// The block number at which this message was sent. /// Specifically, it is the block number at which the candidate that sends this message was @@ -149,7 +144,6 @@ pub struct InboundHrmpMessage { /// An HRMP message seen from the perspective of a sender. #[derive(Encode, Decode, Clone, sp_runtime::RuntimeDebug, PartialEq, Eq, Hash, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct OutboundHrmpMessage { /// The para that will get this message in its downward message queue. pub recipient: Id, diff --git a/erasure-coding/Cargo.toml b/erasure-coding/Cargo.toml index 7df14eaf5799..d6846ce1cc62 100644 --- a/erasure-coding/Cargo.toml +++ b/erasure-coding/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "polkadot-erasure-coding" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] polkadot-primitives = { path = "../primitives" } polkadot-node-primitives = { package = "polkadot-node-primitives", path = "../node/primitives" } novelpoly = { package = "reed-solomon-novelpoly", version = "1.0.0" } parity-scale-codec = { version = "3.1.5", default-features = false, features = ["std", "derive"] } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } thiserror = "1.0.31" diff --git a/erasure-coding/fuzzer/Cargo.toml b/erasure-coding/fuzzer/Cargo.toml index 6c8ad88e3955..bd8632a185f5 100644 --- a/erasure-coding/fuzzer/Cargo.toml +++ b/erasure-coding/fuzzer/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "erasure_coding_fuzzer" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] polkadot-erasure-coding = { path = ".." } diff --git a/erasure-coding/src/lib.rs b/erasure-coding/src/lib.rs index 5e85809f4117..6abd7dce4dd3 100644 --- a/erasure-coding/src/lib.rs +++ b/erasure-coding/src/lib.rs @@ -216,7 +216,7 @@ pub struct Branches<'a, I> { impl<'a, I: AsRef<[u8]>> Branches<'a, I> { /// Get the trie root. pub fn root(&self) -> H256 { - self.root.clone() + self.root } } diff --git a/node/client/Cargo.toml b/node/client/Cargo.toml index bebbb1a66e2c..c62f52138b13 100644 --- a/node/client/Cargo.toml +++ b/node/client/Cargo.toml @@ -1,41 +1,43 @@ [package] name = "polkadot-client" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +async-trait = "0.1.57" +futures = "0.3.21" +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-offchain = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-offchain = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-service = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", package = "sp-beefy" , branch = "polkadot-v0.9.36" } # Polkadot Runtimes polkadot-runtime = { path = "../../runtime/polkadot", optional = true } diff --git a/node/client/src/benchmarking.rs b/node/client/src/benchmarking.rs index 7990bc88d218..17ef63f4ba6e 100644 --- a/node/client/src/benchmarking.rs +++ b/node/client/src/benchmarking.rs @@ -165,7 +165,7 @@ impl BenchmarkCallSigner (), runtime::VERSION.spec_version, runtime::VERSION.transaction_version, - genesis.clone(), + genesis, genesis, (), (), @@ -220,7 +220,7 @@ impl BenchmarkCallSigner (), runtime::VERSION.spec_version, runtime::VERSION.transaction_version, - genesis.clone(), + genesis, genesis, (), (), @@ -274,7 +274,7 @@ impl BenchmarkCallSigner (), runtime::VERSION.spec_version, runtime::VERSION.transaction_version, - genesis.clone(), + genesis, genesis, (), (), @@ -328,7 +328,7 @@ impl BenchmarkCallSigner (), runtime::VERSION.spec_version, runtime::VERSION.transaction_version, - genesis.clone(), + genesis, genesis, (), (), @@ -359,7 +359,7 @@ pub fn benchmark_inherent_data( // Assume that all runtimes have the `timestamp` pallet. let d = std::time::Duration::from_millis(0); let timestamp = sp_timestamp::InherentDataProvider::new(d.into()); - timestamp.provide_inherent_data(&mut inherent_data)?; + futures::executor::block_on(timestamp.provide_inherent_data(&mut inherent_data))?; let para_data = polkadot_primitives::v2::InherentData { bitfields: Vec::new(), @@ -368,8 +368,7 @@ pub fn benchmark_inherent_data( parent_header: header, }; - polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::from_data(para_data) - .provide_inherent_data(&mut inherent_data)?; + inherent_data.put_data(polkadot_primitives::v2::PARACHAINS_INHERENT_IDENTIFIER, ¶_data)?; Ok(inherent_data) } diff --git a/node/client/src/lib.rs b/node/client/src/lib.rs index a254973b99c2..d2c119ba04a8 100644 --- a/node/client/src/lib.rs +++ b/node/client/src/lib.rs @@ -327,13 +327,13 @@ impl UsageProvider for Client { impl sc_client_api::BlockBackend for Client { fn block_body( &self, - id: &BlockId, + hash: ::Hash, ) -> sp_blockchain::Result::Extrinsic>>> { with_client! { self, client, { - client.block_body(id) + client.block_body(hash) } } } @@ -358,12 +358,15 @@ impl sc_client_api::BlockBackend for Client { } } - fn justifications(&self, id: &BlockId) -> sp_blockchain::Result> { + fn justifications( + &self, + hash: ::Hash, + ) -> sp_blockchain::Result> { with_client! { self, client, { - client.justifications(id) + client.justifications(hash) } } } @@ -383,7 +386,7 @@ impl sc_client_api::BlockBackend for Client { fn indexed_transaction( &self, - id: &::Hash, + id: ::Hash, ) -> sp_blockchain::Result>> { with_client! { self, @@ -396,7 +399,7 @@ impl sc_client_api::BlockBackend for Client { fn block_indexed_body( &self, - id: &BlockId, + id: ::Hash, ) -> sp_blockchain::Result>>> { with_client! { self, @@ -421,7 +424,7 @@ impl sc_client_api::BlockBackend for Client { impl sc_client_api::StorageProvider for Client { fn storage( &self, - hash: &::Hash, + hash: ::Hash, key: &StorageKey, ) -> sp_blockchain::Result> { with_client! { @@ -435,7 +438,7 @@ impl sc_client_api::StorageProvider for Client { fn storage_keys( &self, - hash: &::Hash, + hash: ::Hash, key_prefix: &StorageKey, ) -> sp_blockchain::Result> { with_client! { @@ -449,7 +452,7 @@ impl sc_client_api::StorageProvider for Client { fn storage_hash( &self, - hash: &::Hash, + hash: ::Hash, key: &StorageKey, ) -> sp_blockchain::Result::Hash>> { with_client! { @@ -463,7 +466,7 @@ impl sc_client_api::StorageProvider for Client { fn storage_pairs( &self, - hash: &::Hash, + hash: ::Hash, key_prefix: &StorageKey, ) -> sp_blockchain::Result> { with_client! { @@ -477,7 +480,7 @@ impl sc_client_api::StorageProvider for Client { fn storage_keys_iter<'a>( &self, - hash: &::Hash, + hash: ::Hash, prefix: Option<&'a StorageKey>, start_key: Option<&StorageKey>, ) -> sp_blockchain::Result< @@ -494,7 +497,7 @@ impl sc_client_api::StorageProvider for Client { fn child_storage( &self, - hash: &::Hash, + hash: ::Hash, child_info: &ChildInfo, key: &StorageKey, ) -> sp_blockchain::Result> { @@ -509,7 +512,7 @@ impl sc_client_api::StorageProvider for Client { fn child_storage_keys( &self, - hash: &::Hash, + hash: ::Hash, child_info: &ChildInfo, key_prefix: &StorageKey, ) -> sp_blockchain::Result> { @@ -524,7 +527,7 @@ impl sc_client_api::StorageProvider for Client { fn child_storage_keys_iter<'a>( &self, - hash: &::Hash, + hash: ::Hash, child_info: ChildInfo, prefix: Option<&'a StorageKey>, start_key: Option<&StorageKey>, @@ -542,7 +545,7 @@ impl sc_client_api::StorageProvider for Client { fn child_storage_hash( &self, - hash: &::Hash, + hash: ::Hash, child_info: &ChildInfo, key: &StorageKey, ) -> sp_blockchain::Result::Hash>> { diff --git a/node/collation-generation/Cargo.toml b/node/collation-generation/Cargo.toml index c32f8e04e4c8..4f41df5d4510 100644 --- a/node/collation-generation/Cargo.toml +++ b/node/collation-generation/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-node-collation-generation" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -12,8 +12,8 @@ polkadot-node-primitives = { path = "../primitives" } polkadot-node-subsystem = { path = "../subsystem" } polkadot-node-subsystem-util = { path = "../subsystem-util" } polkadot-primitives = { path = "../../primitives" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } thiserror = "1.0.31" parity-scale-codec = { version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } diff --git a/node/core/approval-voting/Cargo.toml b/node/core/approval-voting/Cargo.toml index 8940c5b28efd..5e79e1adcb24 100644 --- a/node/core/approval-voting/Cargo.toml +++ b/node/core/approval-voting/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-node-core-approval-voting" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -13,7 +13,7 @@ bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } lru = "0.8" merlin = "2.0" schnorrkel = "0.9.1" -kvdb = "0.12.0" +kvdb = "0.13.0" derive_more = "0.99.17" thiserror = "1.0.31" @@ -24,21 +24,21 @@ polkadot-primitives = { path = "../../../primitives" } polkadot-node-primitives = { path = "../../primitives" } polkadot-node-jaeger = { path = "../../jaeger" } -sc-keystore = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-consensus = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-consensus-slots = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, features = ["full_crypto"] , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sc-keystore = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-consensus = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-consensus-slots = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, features = ["full_crypto"] , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [dev-dependencies] async-trait = "0.1.57" parking_lot = "0.12.0" rand_core = "0.5.1" # should match schnorrkel -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } assert_matches = "1.4.0" -kvdb-memorydb = "0.12.0" +kvdb-memorydb = "0.13.0" test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../../primitives/test-helpers" } diff --git a/node/core/approval-voting/src/approval_checking.rs b/node/core/approval-voting/src/approval_checking.rs index b513c18895b3..82a9a8c89bf5 100644 --- a/node/core/approval-voting/src/approval_checking.rs +++ b/node/core/approval-voting/src/approval_checking.rs @@ -282,8 +282,8 @@ impl State { /// Constructs an infinite iterator from an array of `TrancheEntry` values. Any missing tranches /// are filled with empty assignments, as they are needed to compute the approved tranches. -fn filled_tranche_iterator<'a>( - tranches: &'a [TrancheEntry], +fn filled_tranche_iterator( + tranches: &[TrancheEntry], ) -> impl Iterator { let mut gap_end = None; diff --git a/node/core/approval-voting/src/approval_db/v1/mod.rs b/node/core/approval-voting/src/approval_db/v1/mod.rs index 03b7aa68f134..858bcb8c36fe 100644 --- a/node/core/approval-voting/src/approval_db/v1/mod.rs +++ b/node/core/approval-voting/src/approval_db/v1/mod.rs @@ -90,41 +90,45 @@ impl Backend for DbBackend { match op { BackendWriteOp::WriteStoredBlockRange(stored_block_range) => { tx.put_vec( - self.config.col_data, + self.config.col_approval_data, &STORED_BLOCKS_KEY, stored_block_range.encode(), ); }, BackendWriteOp::DeleteStoredBlockRange => { - tx.delete(self.config.col_data, &STORED_BLOCKS_KEY); + tx.delete(self.config.col_approval_data, &STORED_BLOCKS_KEY); }, BackendWriteOp::WriteBlocksAtHeight(h, blocks) => { - tx.put_vec(self.config.col_data, &blocks_at_height_key(h), blocks.encode()); + tx.put_vec( + self.config.col_approval_data, + &blocks_at_height_key(h), + blocks.encode(), + ); }, BackendWriteOp::DeleteBlocksAtHeight(h) => { - tx.delete(self.config.col_data, &blocks_at_height_key(h)); + tx.delete(self.config.col_approval_data, &blocks_at_height_key(h)); }, BackendWriteOp::WriteBlockEntry(block_entry) => { let block_entry: BlockEntry = block_entry.into(); tx.put_vec( - self.config.col_data, + self.config.col_approval_data, &block_entry_key(&block_entry.block_hash), block_entry.encode(), ); }, BackendWriteOp::DeleteBlockEntry(hash) => { - tx.delete(self.config.col_data, &block_entry_key(&hash)); + tx.delete(self.config.col_approval_data, &block_entry_key(&hash)); }, BackendWriteOp::WriteCandidateEntry(candidate_entry) => { let candidate_entry: CandidateEntry = candidate_entry.into(); tx.put_vec( - self.config.col_data, + self.config.col_approval_data, &candidate_entry_key(&candidate_entry.candidate.hash()), candidate_entry.encode(), ); }, BackendWriteOp::DeleteCandidateEntry(candidate_hash) => { - tx.delete(self.config.col_data, &candidate_entry_key(&candidate_hash)); + tx.delete(self.config.col_approval_data, &candidate_entry_key(&candidate_hash)); }, } } @@ -149,7 +153,9 @@ pub type Bitfield = BitVec; #[derive(Debug, Clone, Copy)] pub struct Config { /// The column family in the database where data is stored. - pub col_data: u32, + pub col_approval_data: u32, + /// The column of the database where rolling session window data is stored. + pub col_session_data: u32, } /// Details pertaining to our assignment on a block. @@ -243,10 +249,10 @@ pub type Result = std::result::Result; pub(crate) fn load_decode( store: &dyn Database, - col_data: u32, + col_approval_data: u32, key: &[u8], ) -> Result> { - match store.get(col_data, key)? { + match store.get(col_approval_data, key)? { None => Ok(None), Some(raw) => D::decode(&mut &raw[..]).map(Some).map_err(Into::into), } @@ -303,7 +309,7 @@ pub fn load_stored_blocks( store: &dyn Database, config: &Config, ) -> SubsystemResult> { - load_decode(store, config.col_data, STORED_BLOCKS_KEY) + load_decode(store, config.col_approval_data, STORED_BLOCKS_KEY) .map_err(|e| SubsystemError::with_origin("approval-voting", e)) } @@ -313,7 +319,7 @@ pub fn load_blocks_at_height( config: &Config, block_number: &BlockNumber, ) -> SubsystemResult> { - load_decode(store, config.col_data, &blocks_at_height_key(*block_number)) + load_decode(store, config.col_approval_data, &blocks_at_height_key(*block_number)) .map(|x| x.unwrap_or_default()) .map_err(|e| SubsystemError::with_origin("approval-voting", e)) } @@ -324,7 +330,7 @@ pub fn load_block_entry( config: &Config, block_hash: &Hash, ) -> SubsystemResult> { - load_decode(store, config.col_data, &block_entry_key(block_hash)) + load_decode(store, config.col_approval_data, &block_entry_key(block_hash)) .map(|u: Option| u.map(|v| v.into())) .map_err(|e| SubsystemError::with_origin("approval-voting", e)) } @@ -335,7 +341,7 @@ pub fn load_candidate_entry( config: &Config, candidate_hash: &CandidateHash, ) -> SubsystemResult> { - load_decode(store, config.col_data, &candidate_entry_key(candidate_hash)) + load_decode(store, config.col_approval_data, &candidate_entry_key(candidate_hash)) .map(|u: Option| u.map(|v| v.into())) .map_err(|e| SubsystemError::with_origin("approval-voting", e)) } diff --git a/node/core/approval-voting/src/approval_db/v1/tests.rs b/node/core/approval-voting/src/approval_db/v1/tests.rs index 548c64bcef03..06923c6a539f 100644 --- a/node/core/approval-voting/src/approval_db/v1/tests.rs +++ b/node/core/approval-voting/src/approval_db/v1/tests.rs @@ -28,9 +28,12 @@ use std::{collections::HashMap, sync::Arc}; use ::test_helpers::{dummy_candidate_receipt, dummy_candidate_receipt_bad_sig, dummy_hash}; const DATA_COL: u32 = 0; -const NUM_COLUMNS: u32 = 1; +const SESSION_DATA_COL: u32 = 1; -const TEST_CONFIG: Config = Config { col_data: DATA_COL }; +const NUM_COLUMNS: u32 = 2; + +const TEST_CONFIG: Config = + Config { col_approval_data: DATA_COL, col_session_data: SESSION_DATA_COL }; fn make_db() -> (DbBackend, Arc) { let db = kvdb_memorydb::create(NUM_COLUMNS); diff --git a/node/core/approval-voting/src/criteria.rs b/node/core/approval-voting/src/criteria.rs index d7bedc9b0a7f..520a1a745056 100644 --- a/node/core/approval-voting/src/criteria.rs +++ b/node/core/approval-voting/src/criteria.rs @@ -21,7 +21,8 @@ use polkadot_node_primitives::approval::{ self as approval_types, AssignmentCert, AssignmentCertKind, DelayTranche, RelayVRFStory, }; use polkadot_primitives::v2::{ - AssignmentId, AssignmentPair, CandidateHash, CoreIndex, GroupIndex, SessionInfo, ValidatorIndex, + AssignmentId, AssignmentPair, CandidateHash, CoreIndex, GroupIndex, IndexedVec, SessionInfo, + ValidatorIndex, }; use sc_keystore::LocalKeystore; use sp_application_crypto::ByteArray; @@ -138,7 +139,7 @@ pub(crate) struct Config { /// The assignment public keys for validators. assignment_keys: Vec, /// The groups of validators assigned to each core. - validator_groups: Vec>, + validator_groups: IndexedVec>, /// The number of availability cores used by the protocol during this session. n_cores: u32, /// The zeroth delay tranche width. @@ -154,10 +155,10 @@ impl<'a> From<&'a SessionInfo> for Config { Config { assignment_keys: s.assignment_keys.clone(), validator_groups: s.validator_groups.clone(), - n_cores: s.n_cores.clone(), - zeroth_delay_tranche_width: s.zeroth_delay_tranche_width.clone(), - relay_vrf_modulo_samples: s.relay_vrf_modulo_samples.clone(), - n_delay_tranches: s.n_delay_tranches.clone(), + n_cores: s.n_cores, + zeroth_delay_tranche_width: s.zeroth_delay_tranche_width, + relay_vrf_modulo_samples: s.relay_vrf_modulo_samples, + n_delay_tranches: s.n_delay_tranches, } } } @@ -541,11 +542,11 @@ pub(crate) fn check_assignment_cert( } fn is_in_backing_group( - validator_groups: &[Vec], + validator_groups: &IndexedVec>, validator: ValidatorIndex, group: GroupIndex, ) -> bool { - validator_groups.get(group.0 as usize).map_or(false, |g| g.contains(&validator)) + validator_groups.get(group).map_or(false, |g| g.contains(&validator)) } #[cfg(test)] @@ -590,7 +591,10 @@ mod tests { .collect() } - fn basic_groups(n_validators: usize, n_groups: usize) -> Vec> { + fn basic_groups( + n_validators: usize, + n_groups: usize, + ) -> IndexedVec> { let size = n_validators / n_groups; let big_groups = n_validators % n_groups; let scraps = n_groups * size; @@ -631,10 +635,10 @@ mod tests { Sr25519Keyring::Bob, Sr25519Keyring::Charlie, ]), - validator_groups: vec![ + validator_groups: IndexedVec::>::from(vec![ vec![ValidatorIndex(0)], vec![ValidatorIndex(1), ValidatorIndex(2)], - ], + ]), n_cores: 2, zeroth_delay_tranche_width: 10, relay_vrf_modulo_samples: 3, @@ -666,10 +670,10 @@ mod tests { Sr25519Keyring::Bob, Sr25519Keyring::Charlie, ]), - validator_groups: vec![ + validator_groups: IndexedVec::>::from(vec![ vec![ValidatorIndex(0)], vec![ValidatorIndex(1), ValidatorIndex(2)], - ], + ]), n_cores: 2, zeroth_delay_tranche_width: 10, relay_vrf_modulo_samples: 3, @@ -696,7 +700,7 @@ mod tests { Sr25519Keyring::Bob, Sr25519Keyring::Charlie, ]), - validator_groups: vec![], + validator_groups: Default::default(), n_cores: 0, zeroth_delay_tranche_width: 10, relay_vrf_modulo_samples: 3, diff --git a/node/core/approval-voting/src/import.rs b/node/core/approval-voting/src/import.rs index 5413c271e0d6..2331b50b6bb1 100644 --- a/node/core/approval-voting/src/import.rs +++ b/node/core/approval-voting/src/import.rs @@ -415,11 +415,8 @@ pub(crate) async fn handle_new_head( Err(error) => { // It's possible that we've lost a race with finality. let (tx, rx) = oneshot::channel(); - ctx.send_message(ChainApiMessage::FinalizedBlockHash( - block_header.number.clone(), - tx, - )) - .await; + ctx.send_message(ChainApiMessage::FinalizedBlockHash(block_header.number, tx)) + .await; let lost_to_finality = match rx.await { Ok(Ok(Some(h))) if h != block_hash => true, @@ -620,7 +617,9 @@ pub(crate) mod tests { use polkadot_node_subsystem::messages::{AllMessages, ApprovalVotingMessage}; use polkadot_node_subsystem_test_helpers::make_subsystem_context; use polkadot_node_subsystem_util::database::Database; - use polkadot_primitives::v2::{Id as ParaId, SessionInfo, ValidatorIndex}; + use polkadot_primitives::v2::{ + Id as ParaId, IndexedVec, SessionInfo, ValidatorId, ValidatorIndex, + }; pub(crate) use sp_consensus_babe::{ digests::{CompatibleDigestItem, PreDigest, SecondaryVRFPreDigest}, AllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch, @@ -630,14 +629,15 @@ pub(crate) mod tests { pub(crate) use sp_runtime::{Digest, DigestItem}; use std::{pin::Pin, sync::Arc}; - use crate::{ - approval_db::v1::Config as DatabaseConfig, criteria, BlockEntry, APPROVAL_SESSIONS, - }; + use crate::{approval_db::v1::Config as DatabaseConfig, criteria, BlockEntry}; const DATA_COL: u32 = 0; - const NUM_COLUMNS: u32 = 1; + const SESSION_DATA_COL: u32 = 1; + + const NUM_COLUMNS: u32 = 2; - const TEST_CONFIG: DatabaseConfig = DatabaseConfig { col_data: DATA_COL }; + const TEST_CONFIG: DatabaseConfig = + DatabaseConfig { col_approval_data: DATA_COL, col_session_data: SESSION_DATA_COL }; #[derive(Default)] struct MockClock; @@ -652,22 +652,23 @@ pub(crate) mod tests { } fn blank_state() -> State { + let db = kvdb_memorydb::create(NUM_COLUMNS); + let db = polkadot_node_subsystem_util::database::kvdb_impl::DbAdapter::new(db, &[]); + let db: Arc = Arc::new(db); State { session_window: None, keystore: Arc::new(LocalKeystore::in_memory()), slot_duration_millis: 6_000, clock: Box::new(MockClock::default()), assignment_criteria: Box::new(MockAssignmentCriteria), + db, + db_config: TEST_CONFIG, } } fn single_session_state(index: SessionIndex, info: SessionInfo) -> State { State { - session_window: Some(RollingSessionWindow::with_session_info( - APPROVAL_SESSIONS, - index, - vec![info], - )), + session_window: Some(RollingSessionWindow::with_session_info(index, vec![info])), ..blank_state() } } @@ -713,10 +714,10 @@ pub(crate) mod tests { fn dummy_session_info(index: SessionIndex) -> SessionInfo { SessionInfo { - validators: Vec::new(), + validators: Default::default(), discovery_keys: Vec::new(), assignment_keys: Vec::new(), - validator_groups: Vec::new(), + validator_groups: Default::default(), n_cores: index as _, zeroth_delay_tranche_width: index as _, relay_vrf_modulo_samples: index as _, @@ -780,11 +781,8 @@ pub(crate) mod tests { .map(|(r, c, g)| (r.hash(), r.clone(), *c, *g)) .collect::>(); - let session_window = RollingSessionWindow::with_session_info( - APPROVAL_SESSIONS, - session, - vec![session_info], - ); + let session_window = + RollingSessionWindow::with_session_info(session, vec![session_info]); let header = header.clone(); Box::pin(async move { @@ -889,11 +887,8 @@ pub(crate) mod tests { .collect::>(); let test_fut = { - let session_window = RollingSessionWindow::with_session_info( - APPROVAL_SESSIONS, - session, - vec![session_info], - ); + let session_window = + RollingSessionWindow::with_session_info(session, vec![session_info]); let header = header.clone(); Box::pin(async move { @@ -1087,11 +1082,8 @@ pub(crate) mod tests { .map(|(r, c, g)| (r.hash(), r.clone(), *c, *g)) .collect::>(); - let session_window = Some(RollingSessionWindow::with_session_info( - APPROVAL_SESSIONS, - session, - vec![session_info], - )); + let session_window = + Some(RollingSessionWindow::with_session_info(session, vec![session_info])); let header = header.clone(); Box::pin(async move { @@ -1174,21 +1166,27 @@ pub(crate) mod tests { let session = 5; let irrelevant = 666; - let session_info = SessionInfo { - validators: vec![Sr25519Keyring::Alice.public().into(); 6], - discovery_keys: Vec::new(), - assignment_keys: Vec::new(), - validator_groups: vec![vec![ValidatorIndex(0); 5], vec![ValidatorIndex(0); 2]], - n_cores: 6, - needed_approvals: 2, - zeroth_delay_tranche_width: irrelevant, - relay_vrf_modulo_samples: irrelevant, - n_delay_tranches: irrelevant, - no_show_slots: irrelevant, - active_validator_indices: Vec::new(), - dispute_period: 6, - random_seed: [0u8; 32], - }; + let session_info = + SessionInfo { + validators: IndexedVec::::from( + vec![Sr25519Keyring::Alice.public().into(); 6], + ), + discovery_keys: Vec::new(), + assignment_keys: Vec::new(), + validator_groups: IndexedVec::>::from(vec![ + vec![ValidatorIndex(0); 5], + vec![ValidatorIndex(0); 2], + ]), + n_cores: 6, + needed_approvals: 2, + zeroth_delay_tranche_width: irrelevant, + relay_vrf_modulo_samples: irrelevant, + n_delay_tranches: irrelevant, + no_show_slots: irrelevant, + active_validator_indices: Vec::new(), + dispute_period: 6, + random_seed: [0u8; 32], + }; let slot = Slot::from(10); @@ -1296,38 +1294,6 @@ pub(crate) mod tests { } ); - // Caching of sesssions needs sessoion of first unfinalied block. - assert_matches!( - handle.recv().await, - AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber( - s_tx, - )) => { - let _ = s_tx.send(Ok(header.number)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::ChainApi(ChainApiMessage::FinalizedBlockHash( - block_number, - s_tx, - )) => { - assert_eq!(block_number, header.number); - let _ = s_tx.send(Ok(Some(header.hash()))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - h, - RuntimeApiRequest::SessionIndexForChild(s_tx), - )) => { - assert_eq!(h, header.hash()); - let _ = s_tx.send(Ok(session)); - } - ); - // determine_new_blocks exits early as the parent_hash is in the DB assert_matches!( diff --git a/node/core/approval-voting/src/lib.rs b/node/core/approval-voting/src/lib.rs index 467d8be612e9..14fc87761c42 100644 --- a/node/core/approval-voting/src/lib.rs +++ b/node/core/approval-voting/src/lib.rs @@ -44,8 +44,7 @@ use polkadot_node_subsystem_util::{ database::Database, metrics::{self, prometheus}, rolling_session_window::{ - new_session_window_size, RollingSessionWindow, SessionWindowSize, SessionWindowUpdate, - SessionsUnavailable, + DatabaseParams, RollingSessionWindow, SessionWindowUpdate, SessionsUnavailable, }, TimeoutExt, }; @@ -97,8 +96,6 @@ use crate::{ #[cfg(test)] mod tests; -pub const APPROVAL_SESSIONS: SessionWindowSize = new_session_window_size!(6); - const APPROVAL_CHECKING_TIMEOUT: Duration = Duration::from_secs(120); /// How long are we willing to wait for approval signatures? /// @@ -118,7 +115,9 @@ const LOG_TARGET: &str = "parachain::approval-voting"; #[derive(Debug, Clone)] pub struct Config { /// The column family in the DB where approval-voting data is stored. - pub col_data: u32, + pub col_approval_data: u32, + /// The of the DB where rolling session info is stored. + pub col_session_data: u32, /// The slot duration of the consensus algorithm, in milliseconds. Should be evenly /// divisible by 500. pub slot_duration_millis: u64, @@ -358,7 +357,10 @@ impl ApprovalVotingSubsystem { keystore, slot_duration_millis: config.slot_duration_millis, db, - db_config: DatabaseConfig { col_data: config.col_data }, + db_config: DatabaseConfig { + col_approval_data: config.col_approval_data, + col_session_data: config.col_session_data, + }, mode: Mode::Syncing(sync_oracle), metrics, } @@ -367,7 +369,10 @@ impl ApprovalVotingSubsystem { /// Revert to the block corresponding to the specified `hash`. /// The operation is not allowed for blocks older than the last finalized one. pub fn revert_to(&self, hash: Hash) -> Result<(), SubsystemError> { - let config = approval_db::v1::Config { col_data: self.db_config.col_data }; + let config = approval_db::v1::Config { + col_approval_data: self.db_config.col_approval_data, + col_session_data: self.db_config.col_session_data, + }; let mut backend = approval_db::v1::DbBackend::new(self.db.clone(), config); let mut overlay = OverlayedBackend::new(&backend); @@ -378,6 +383,25 @@ impl ApprovalVotingSubsystem { } } +// Checks and logs approval vote db state. It is perfectly normal to start with an +// empty approval vote DB if we changed DB type or the node will sync from scratch. +fn db_sanity_check(db: Arc, config: DatabaseConfig) -> SubsystemResult<()> { + let backend = DbBackend::new(db, config); + let all_blocks = backend.load_all_blocks()?; + + if all_blocks.is_empty() { + gum::info!(target: LOG_TARGET, "Starting with an empty approval vote DB.",); + } else { + gum::debug!( + target: LOG_TARGET, + "Starting with {} blocks in approval vote DB.", + all_blocks.len() + ); + } + + Ok(()) +} + #[overseer::subsystem(ApprovalVoting, error = SubsystemError, prefix = self::overseer)] impl ApprovalVotingSubsystem { fn start(self, ctx: Context) -> SpawnedSubsystem { @@ -597,10 +621,7 @@ impl CurrentlyCheckingSet { .candidate_hash_map .remove(&approval_state.candidate_hash) .unwrap_or_default(); - approvals_cache.put( - approval_state.candidate_hash.clone(), - approval_state.approval_outcome.clone(), - ); + approvals_cache.put(approval_state.candidate_hash, approval_state.approval_outcome); return (out, approval_state) } } @@ -615,6 +636,9 @@ struct State { slot_duration_millis: u64, clock: Box, assignment_criteria: Box, + // Require for `RollingSessionWindow`. + db_config: DatabaseConfig, + db: Arc, } #[overseer::contextbounds(ApprovalVoting, prefix = self::overseer)] @@ -636,8 +660,17 @@ impl State { match session_window { None => { let sender = ctx.sender().clone(); - self.session_window = - Some(RollingSessionWindow::new(sender, APPROVAL_SESSIONS, head).await?); + self.session_window = Some( + RollingSessionWindow::new( + sender, + head, + DatabaseParams { + db: self.db.clone(), + db_column: self.db_config.col_session_data, + }, + ) + .await?, + ); Ok(None) }, Some(mut session_window) => { @@ -732,12 +765,18 @@ async fn run( where B: Backend, { + if let Err(err) = db_sanity_check(subsystem.db.clone(), subsystem.db_config) { + gum::warn!(target: LOG_TARGET, ?err, "Could not run approval vote DB sanity check"); + } + let mut state = State { session_window: None, keystore: subsystem.keystore, slot_duration_millis: subsystem.slot_duration_millis, clock, assignment_criteria, + db_config: subsystem.db_config, + db: subsystem.db, }; let mut wakeups = Wakeups::default(); @@ -1102,7 +1141,7 @@ async fn handle_from_overseer( FromOrchestra::Signal(OverseerSignal::ActiveLeaves(update)) => { let mut actions = Vec::new(); - for activated in update.activated { + if let Some(activated) = update.activated { let head = activated.hash; match import::handle_new_head(ctx, state, db, head, &*last_finalized_height).await { Err(e) => return Err(SubsystemError::with_origin("db", e)), @@ -1236,7 +1275,7 @@ async fn get_approval_signatures_for_candidate( Some(e) => e, }; - let relay_hashes = entry.block_assignments.iter().map(|(relay_hash, _)| relay_hash); + let relay_hashes = entry.block_assignments.keys(); let mut candidate_indices = HashSet::new(); // Retrieve `CoreIndices`/`CandidateIndices` as required by approval-distribution: @@ -1288,6 +1327,11 @@ async fn get_approval_signatures_for_candidate( // No need to block subsystem on this (also required to break cycle). // We should not be sending this message frequently - caller must make sure this is bounded. + gum::trace!( + target: LOG_TARGET, + ?candidate_hash, + "Spawning task for fetching sinatures from approval-distribution" + ); ctx.spawn("get-approval-signatures", Box::pin(get_approvals)) } @@ -1803,7 +1847,7 @@ fn check_and_import_approval( )), }; - let pubkey = match session_info.validators.get(approval.validator.0 as usize) { + let pubkey = match session_info.validators.get(approval.validator) { Some(k) => k, None => respond_early!(ApprovalCheckResult::Bad( ApprovalCheckError::InvalidValidatorIndex(approval.validator), @@ -2362,28 +2406,14 @@ async fn launch_approval( match val_rx.await { Err(_) => return ApprovalState::failed(validator_index, candidate_hash), - Ok(Ok(ValidationResult::Valid(commitments, _))) => { + Ok(Ok(ValidationResult::Valid(_, _))) => { // Validation checked out. Issue an approval command. If the underlying service is unreachable, // then there isn't anything we can do. gum::trace!(target: LOG_TARGET, ?candidate_hash, ?para_id, "Candidate Valid"); - let expected_commitments_hash = candidate.commitments_hash; - if commitments.hash() == expected_commitments_hash { - let _ = metrics_guard.take(); - return ApprovalState::approved(validator_index, candidate_hash) - } else { - // Commitments mismatch - issue a dispute. - issue_local_invalid_statement( - &mut sender, - session_index, - candidate_hash, - candidate.clone(), - ); - - metrics_guard.take().on_approval_invalid(); - return ApprovalState::failed(validator_index, candidate_hash) - } + let _ = metrics_guard.take(); + return ApprovalState::approved(validator_index, candidate_hash) }, Ok(Ok(ValidationResult::Invalid(reason))) => { gum::warn!( @@ -2474,7 +2504,7 @@ async fn issue_approval( }; let candidate_hash = match block_entry.candidate(candidate_index as usize) { - Some((_, h)) => h.clone(), + Some((_, h)) => *h, None => { gum::warn!( target: LOG_TARGET, @@ -2503,7 +2533,7 @@ async fn issue_approval( }, }; - let validator_pubkey = match session_info.validators.get(validator_index.0 as usize) { + let validator_pubkey = match session_info.validators.get(validator_index) { Some(p) => p, None => { gum::warn!( diff --git a/node/core/approval-voting/src/tests.rs b/node/core/approval-voting/src/tests.rs index bdb7a8c929b3..b9063c8ade25 100644 --- a/node/core/approval-voting/src/tests.rs +++ b/node/core/approval-voting/src/tests.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +use crate::tests::test_constants::TEST_CONFIG; + use super::*; use polkadot_node_primitives::{ approval::{ @@ -32,7 +34,7 @@ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_overseer::HeadSupportsParachains; use polkadot_primitives::v2::{ - CandidateCommitments, CandidateEvent, CoreIndex, GroupIndex, Header, Id as ParaId, + CandidateCommitments, CandidateEvent, CoreIndex, GroupIndex, Header, Id as ParaId, IndexedVec, ValidationCode, ValidatorSignature, }; use std::time::Duration; @@ -111,9 +113,12 @@ fn make_sync_oracle(val: bool) -> (Box, TestSyncOracleHan pub mod test_constants { use crate::approval_db::v1::Config as DatabaseConfig; const DATA_COL: u32 = 0; - pub(crate) const NUM_COLUMNS: u32 = 1; + const SESSION_DATA_COL: u32 = 1; + + pub(crate) const NUM_COLUMNS: u32 = 2; - pub(crate) const TEST_CONFIG: DatabaseConfig = DatabaseConfig { col_data: DATA_COL }; + pub(crate) const TEST_CONFIG: DatabaseConfig = + DatabaseConfig { col_approval_data: DATA_COL, col_session_data: SESSION_DATA_COL }; } struct MockSupportsParachains; @@ -487,8 +492,9 @@ fn test_harness>( context, ApprovalVotingSubsystem::with_config( Config { - col_data: test_constants::TEST_CONFIG.col_data, + col_approval_data: test_constants::TEST_CONFIG.col_approval_data, slot_duration_millis: SLOT_DURATION_MILLIS, + col_session_data: TEST_CONFIG.col_session_data, }, Arc::new(db), Arc::new(keystore), @@ -739,7 +745,10 @@ fn session_info(keys: &[Sr25519Keyring]) -> SessionInfo { validators: keys.iter().map(|v| v.public().into()).collect(), discovery_keys: keys.iter().map(|v| v.public().into()).collect(), assignment_keys: keys.iter().map(|v| v.public().into()).collect(), - validator_groups: vec![vec![ValidatorIndex(0)], vec![ValidatorIndex(1)]], + validator_groups: IndexedVec::>::from(vec![ + vec![ValidatorIndex(0)], + vec![ValidatorIndex(1)], + ]), n_cores: keys.len() as _, needed_approvals: 2, zeroth_delay_tranche_width: 5, @@ -807,38 +816,38 @@ async fn import_block( } ); - assert_matches!( - overseer_recv(overseer).await, - AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber( - s_tx, - )) => { - let _ = s_tx.send(Ok(number)); - } - ); + if !fork { + assert_matches!( + overseer_recv(overseer).await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber( + s_tx, + )) => { + let _ = s_tx.send(Ok(number)); + } + ); - assert_matches!( - overseer_recv(overseer).await, - AllMessages::ChainApi(ChainApiMessage::FinalizedBlockHash( - block_number, - s_tx, - )) => { - assert_eq!(block_number, number); - let _ = s_tx.send(Ok(Some(hashes[number as usize].0))); - } - ); + assert_matches!( + overseer_recv(overseer).await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockHash( + block_number, + s_tx, + )) => { + assert_eq!(block_number, number); + let _ = s_tx.send(Ok(Some(hashes[number as usize].0))); + } + ); - assert_matches!( - overseer_recv(overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - h, - RuntimeApiRequest::SessionIndexForChild(s_tx), - )) => { - assert_eq!(h, hashes[number as usize].0); - let _ = s_tx.send(Ok(number.into())); - } - ); + assert_matches!( + overseer_recv(overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + h, + RuntimeApiRequest::SessionIndexForChild(s_tx), + )) => { + assert_eq!(h, hashes[number as usize].0); + let _ = s_tx.send(Ok(number.into())); + } + ); - if !fork { assert_matches!( overseer_recv(overseer).await, AllMessages::RuntimeApi( @@ -1552,11 +1561,11 @@ fn subsystem_second_approval_import_only_schedules_wakeups() { Sr25519Keyring::Eve, ]; let session_info = SessionInfo { - validator_groups: vec![ + validator_groups: IndexedVec::>::from(vec![ vec![ValidatorIndex(0), ValidatorIndex(1)], vec![ValidatorIndex(2)], vec![ValidatorIndex(3), ValidatorIndex(4)], - ], + ]), needed_approvals: 1, ..session_info(&validators) }; @@ -1889,11 +1898,11 @@ fn import_checked_approval_updates_entries_and_schedules() { Sr25519Keyring::Eve, ]; let session_info = SessionInfo { - validator_groups: vec![ + validator_groups: IndexedVec::>::from(vec![ vec![ValidatorIndex(0), ValidatorIndex(1)], vec![ValidatorIndex(2)], vec![ValidatorIndex(3), ValidatorIndex(4)], - ], + ]), ..session_info(&validators) }; @@ -2046,11 +2055,11 @@ fn subsystem_import_checked_approval_sets_one_block_bit_at_a_time() { Sr25519Keyring::Eve, ]; let session_info = SessionInfo { - validator_groups: vec![ + validator_groups: IndexedVec::>::from(vec![ vec![ValidatorIndex(0), ValidatorIndex(1)], vec![ValidatorIndex(2)], vec![ValidatorIndex(3), ValidatorIndex(4)], - ], + ]), ..session_info(&validators) }; @@ -2336,11 +2345,11 @@ fn subsystem_validate_approvals_cache() { Sr25519Keyring::Eve, ]; let session_info = SessionInfo { - validator_groups: vec![ + validator_groups: IndexedVec::>::from(vec![ vec![ValidatorIndex(0), ValidatorIndex(1)], vec![ValidatorIndex(2)], vec![ValidatorIndex(3), ValidatorIndex(4)], - ], + ]), ..session_info(&validators) }; @@ -2548,11 +2557,11 @@ where Sr25519Keyring::Ferdie, ]; let session_info = SessionInfo { - validator_groups: vec![ + validator_groups: IndexedVec::>::from(vec![ vec![ValidatorIndex(0), ValidatorIndex(1)], vec![ValidatorIndex(2), ValidatorIndex(3)], vec![ValidatorIndex(4), ValidatorIndex(5)], - ], + ]), relay_vrf_modulo_samples: 2, no_show_slots, ..session_info(&validators) @@ -2868,11 +2877,11 @@ fn pre_covers_dont_stall_approval() { Sr25519Keyring::One, ]; let session_info = SessionInfo { - validator_groups: vec![ + validator_groups: IndexedVec::>::from(vec![ vec![ValidatorIndex(0), ValidatorIndex(1)], vec![ValidatorIndex(2), ValidatorIndex(5)], vec![ValidatorIndex(3), ValidatorIndex(4)], - ], + ]), ..session_info(&validators) }; @@ -3045,11 +3054,11 @@ fn waits_until_approving_assignments_are_old_enough() { Sr25519Keyring::One, ]; let session_info = SessionInfo { - validator_groups: vec![ + validator_groups: IndexedVec::>::from(vec![ vec![ValidatorIndex(0), ValidatorIndex(1)], vec![ValidatorIndex(2), ValidatorIndex(5)], vec![ValidatorIndex(3), ValidatorIndex(4)], - ], + ]), ..session_info(&validators) }; diff --git a/node/core/av-store/Cargo.toml b/node/core/av-store/Cargo.toml index b4d19e430aad..fd03cc2bd2e6 100644 --- a/node/core/av-store/Cargo.toml +++ b/node/core/av-store/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "polkadot-node-core-av-store" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" futures-timer = "3.0.2" -kvdb = "0.12.0" +kvdb = "0.13.0" thiserror = "1.0.31" gum = { package = "tracing-gum", path = "../../gum" } bitvec = "1.0.0" @@ -24,11 +24,11 @@ polkadot-node-primitives = { path = "../../primitives" } log = "0.4.17" env_logger = "0.9.0" assert_matches = "1.4.0" -kvdb-memorydb = "0.12.0" +kvdb-memorydb = "0.13.0" -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } parking_lot = "0.12.0" test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../../primitives/test-helpers" } diff --git a/node/core/av-store/src/lib.rs b/node/core/av-store/src/lib.rs index 4fbbf3740ab0..cbbbf2bbd7dc 100644 --- a/node/core/av-store/src/lib.rs +++ b/node/core/av-store/src/lib.rs @@ -61,7 +61,7 @@ const PRUNE_BY_TIME_PREFIX: &[u8; 13] = b"prune_by_time"; // We have some keys we want to map to empty values because existence of the key is enough. We use this because // rocksdb doesn't support empty values. -const TOMBSTONE_VALUE: &[u8] = &*b" "; +const TOMBSTONE_VALUE: &[u8] = b" "; /// Unavailable blocks are kept for 1 hour. const KEEP_UNAVAILABLE_FOR: Duration = Duration::from_secs(60 * 60); diff --git a/node/core/av-store/src/metrics.rs b/node/core/av-store/src/metrics.rs index c50932c6173e..fedeb2b7d0e5 100644 --- a/node/core/av-store/src/metrics.rs +++ b/node/core/av-store/src/metrics.rs @@ -140,10 +140,16 @@ impl metrics::Metrics for Metrics { registry, )?, get_chunk: prometheus::register( - prometheus::Histogram::with_opts(prometheus::HistogramOpts::new( - "polkadot_parachain_av_store_get_chunk", - "Time spent fetching requested chunks.`", - ))?, + prometheus::Histogram::with_opts( + prometheus::HistogramOpts::new( + "polkadot_parachain_av_store_get_chunk", + "Time spent fetching requested chunks.`", + ) + .buckets(vec![ + 0.000625, 0.00125, 0.0025, 0.005, 0.0075, 0.01, 0.025, 0.05, 0.1, 0.25, + 0.5, 1.0, 2.5, 5.0, 10.0, + ]), + )?, registry, )?, }; diff --git a/node/core/backing/Cargo.toml b/node/core/backing/Cargo.toml index 1fb8c9f46d99..2fb3902f321e 100644 --- a/node/core/backing/Cargo.toml +++ b/node/core/backing/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "polkadot-node-core-backing" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-primitives = { path = "../../../primitives" } polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem = {path = "../../subsystem" } @@ -19,11 +19,11 @@ thiserror = "1.0.31" fatality = "0.0.6" [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures = { version = "0.3.21", features = ["thread-pool"] } assert_matches = "1.4.0" polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } diff --git a/node/core/backing/src/lib.rs b/node/core/backing/src/lib.rs index a9ae518e3103..2f8aa4490f27 100644 --- a/node/core/backing/src/lib.rs +++ b/node/core/backing/src/lib.rs @@ -482,9 +482,7 @@ impl TableContextTrait for TableContext { } fn is_member_of(&self, authority: &ValidatorIndex, group: &ParaId) -> bool { - self.groups - .get(group) - .map_or(false, |g| g.iter().position(|a| a == authority).is_some()) + self.groups.get(group).map_or(false, |g| g.iter().any(|a| a == authority)) } fn requisite_votes(&self, group: &ParaId) -> usize { @@ -499,7 +497,7 @@ struct InvalidErasureRoot; fn primitive_statement_to_table(s: &SignedFullStatement) -> TableSignedStatement { let statement = match s.payload() { Statement::Seconded(c) => TableStatement::Seconded(c.clone()), - Statement::Valid(h) => TableStatement::Valid(h.clone()), + Statement::Valid(h) => TableStatement::Valid(*h), }; TableSignedStatement { diff --git a/node/core/bitfield-signing/Cargo.toml b/node/core/bitfield-signing/Cargo.toml index 93e7e6683fc5..9dc391f9bbbf 100644 --- a/node/core/bitfield-signing/Cargo.toml +++ b/node/core/bitfield-signing/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-node-core-bitfield-signing" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -10,7 +10,7 @@ gum = { package = "tracing-gum", path = "../../gum" } polkadot-primitives = { path = "../../../primitives" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } wasm-timer = "0.2.5" thiserror = "1.0.31" diff --git a/node/core/bitfield-signing/src/lib.rs b/node/core/bitfield-signing/src/lib.rs index 13a3dd28705f..64cbb18cc44c 100644 --- a/node/core/bitfield-signing/src/lib.rs +++ b/node/core/bitfield-signing/src/lib.rs @@ -225,7 +225,7 @@ async fn run( } } - for leaf in update.activated { + if let Some(leaf) = update.activated { let sender = ctx.sender().clone(); let leaf_hash = leaf.hash; diff --git a/node/core/bitfield-signing/src/metrics.rs b/node/core/bitfield-signing/src/metrics.rs index ab4e73be0eeb..571a0c335bd7 100644 --- a/node/core/bitfield-signing/src/metrics.rs +++ b/node/core/bitfield-signing/src/metrics.rs @@ -50,10 +50,16 @@ impl metrics::Metrics for Metrics { registry, )?, run: prometheus::register( - prometheus::Histogram::with_opts(prometheus::HistogramOpts::new( - "polkadot_parachain_bitfield_signing_run", - "Time spent within `bitfield_signing::run`", - ))?, + prometheus::Histogram::with_opts( + prometheus::HistogramOpts::new( + "polkadot_parachain_bitfield_signing_run", + "Time spent within `bitfield_signing::run`", + ) + .buckets(vec![ + 0.000625, 0.00125, 0.0025, 0.005, 0.0075, 0.01, 0.025, 0.05, 0.1, 0.25, + 0.5, 1.0, 2.5, 5.0, 10.0, + ]), + )?, registry, )?, }; diff --git a/node/core/candidate-validation/Cargo.toml b/node/core/candidate-validation/Cargo.toml index ad1da736e01f..545f42059b6b 100644 --- a/node/core/candidate-validation/Cargo.toml +++ b/node/core/candidate-validation/Cargo.toml @@ -1,15 +1,16 @@ [package] name = "polkadot-node-core-candidate-validation" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] async-trait = "0.1.57" futures = "0.3.21" +futures-timer = "3.0.2" gum = { package = "tracing-gum", path = "../../gum" } -sp-maybe-compressed-blob = { package = "sp-maybe-compressed-blob", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-maybe-compressed-blob = { package = "sp-maybe-compressed-blob", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } parity-scale-codec = { version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } polkadot-primitives = { path = "../../../primitives" } @@ -22,9 +23,9 @@ polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-core-pvf = { path = "../pvf" } [dev-dependencies] -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures = { version = "0.3.21", features = ["thread-pool"] } assert_matches = "1.4.0" polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../../primitives/test-helpers" } diff --git a/node/core/candidate-validation/src/lib.rs b/node/core/candidate-validation/src/lib.rs index c3775ba1c453..74610bc113ec 100644 --- a/node/core/candidate-validation/src/lib.rs +++ b/node/core/candidate-validation/src/lib.rs @@ -60,6 +60,12 @@ mod tests; const LOG_TARGET: &'static str = "parachain::candidate-validation"; +/// The amount of time to wait before retrying after an AmbiguousWorkerDeath validation error. +#[cfg(not(test))] +const PVF_EXECUTION_RETRY_DELAY: Duration = Duration::from_secs(3); +#[cfg(test)] +const PVF_EXECUTION_RETRY_DELAY: Duration = Duration::from_millis(200); + /// Configuration for the candidate validation subsystem #[derive(Clone)] pub struct Config { @@ -461,11 +467,6 @@ where .await; if let Ok(ValidationResult::Valid(ref outputs, _)) = validation_result { - // If validation produces new commitments we consider the candidate invalid. - if candidate_receipt.commitments_hash != outputs.hash() { - return Ok(ValidationResult::Invalid(InvalidCandidate::CommitmentsHashMismatch)) - } - let (tx, rx) = oneshot::channel(); match runtime_api_request( sender, @@ -490,7 +491,7 @@ where } async fn validate_candidate_exhaustive( - mut validation_backend: impl ValidationBackend, + mut validation_backend: impl ValidationBackend + Send, persisted_validation_data: PersistedValidationData, validation_code: ValidationCode, candidate_receipt: CandidateReceipt, @@ -501,7 +502,7 @@ async fn validate_candidate_exhaustive( let _timer = metrics.time_validate_candidate_exhaustive(); let validation_code_hash = validation_code.hash(); - let para_id = candidate_receipt.descriptor.para_id.clone(); + let para_id = candidate_receipt.descriptor.para_id; gum::debug!( target: LOG_TARGET, ?validation_code_hash, @@ -512,7 +513,7 @@ async fn validate_candidate_exhaustive( if let Err(e) = perform_basic_checks( &candidate_receipt.descriptor, persisted_validation_data.max_pov_size, - &*pov, + &pov, &validation_code_hash, ) { gum::info!(target: LOG_TARGET, ?para_id, "Invalid candidate (basic checks)"); @@ -551,7 +552,7 @@ async fn validate_candidate_exhaustive( }; let result = validation_backend - .validate_candidate(raw_validation_code.to_vec(), timeout, params) + .validate_candidate_with_retry(raw_validation_code.to_vec(), timeout, params) .await; if let Err(ref error) = result { @@ -604,48 +605,66 @@ async fn validate_candidate_exhaustive( #[async_trait] trait ValidationBackend { async fn validate_candidate( + &mut self, + pvf: Pvf, + timeout: Duration, + encoded_params: Vec, + ) -> Result; + + async fn validate_candidate_with_retry( &mut self, raw_validation_code: Vec, timeout: Duration, params: ValidationParams, - ) -> Result; + ) -> Result { + // Construct the PVF a single time, since it is an expensive operation. Cloning it is cheap. + let pvf = Pvf::from_code(raw_validation_code); - async fn precheck_pvf(&mut self, pvf: Pvf) -> Result<(), PrepareError>; + let validation_result = + self.validate_candidate(pvf.clone(), timeout, params.encode()).await; + + // If we get an AmbiguousWorkerDeath error, retry once after a brief delay, on the + // assumption that the conditions that caused this error may have been transient. + if let Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::AmbiguousWorkerDeath)) = + validation_result + { + // Wait a brief delay before retrying. + futures_timer::Delay::new(PVF_EXECUTION_RETRY_DELAY).await; + // Encode the params again when re-trying. We expect the retry case to be relatively + // rare, and we want to avoid unconditionally cloning data. + self.validate_candidate(pvf, timeout, params.encode()).await + } else { + validation_result + } + } + + async fn precheck_pvf(&mut self, pvf: Pvf) -> Result; } #[async_trait] impl ValidationBackend for ValidationHost { + /// Tries executing a PVF a single time (no retries). async fn validate_candidate( &mut self, - raw_validation_code: Vec, + pvf: Pvf, timeout: Duration, - params: ValidationParams, + encoded_params: Vec, ) -> Result { + let priority = polkadot_node_core_pvf::Priority::Normal; + let (tx, rx) = oneshot::channel(); - if let Err(err) = self - .execute_pvf( - Pvf::from_code(raw_validation_code), - timeout, - params.encode(), - polkadot_node_core_pvf::Priority::Normal, - tx, - ) - .await - { + if let Err(err) = self.execute_pvf(pvf, timeout, encoded_params, priority, tx).await { return Err(ValidationError::InternalError(format!( "cannot send pvf to the validation host: {:?}", err ))) } - let validation_result = rx - .await - .map_err(|_| ValidationError::InternalError("validation was cancelled".into()))?; - - validation_result + rx.await + .map_err(|_| ValidationError::InternalError("validation was cancelled".into()))? } - async fn precheck_pvf(&mut self, pvf: Pvf) -> Result<(), PrepareError> { + async fn precheck_pvf(&mut self, pvf: Pvf) -> Result { let (tx, rx) = oneshot::channel(); if let Err(_) = self.precheck_pvf(pvf, tx).await { return Err(PrepareError::DidNotMakeIt) diff --git a/node/core/candidate-validation/src/tests.rs b/node/core/candidate-validation/src/tests.rs index ecac13d1440d..5ac93bc7d1f4 100644 --- a/node/core/candidate-validation/src/tests.rs +++ b/node/core/candidate-validation/src/tests.rs @@ -345,12 +345,19 @@ fn check_does_not_match() { } struct MockValidateCandidateBackend { - result: Result, + result_list: Vec>, + num_times_called: usize, } impl MockValidateCandidateBackend { fn with_hardcoded_result(result: Result) -> Self { - Self { result } + Self { result_list: vec![result], num_times_called: 0 } + } + + fn with_hardcoded_result_list( + result_list: Vec>, + ) -> Self { + Self { result_list, num_times_called: 0 } } } @@ -358,14 +365,19 @@ impl MockValidateCandidateBackend { impl ValidationBackend for MockValidateCandidateBackend { async fn validate_candidate( &mut self, - _raw_validation_code: Vec, + _pvf: Pvf, _timeout: Duration, - _params: ValidationParams, + _encoded_params: Vec, ) -> Result { - self.result.clone() + // This is expected to panic if called more times than expected, indicating an error in the + // test. + let result = self.result_list[self.num_times_called].clone(); + self.num_times_called += 1; + + result } - async fn precheck_pvf(&mut self, _pvf: Pvf) -> Result<(), PrepareError> { + async fn precheck_pvf(&mut self, _pvf: Pvf) -> Result { unreachable!() } } @@ -468,7 +480,7 @@ fn candidate_validation_bad_return_is_invalid() { let v = executor::block_on(validate_candidate_exhaustive( MockValidateCandidateBackend::with_hardcoded_result(Err( - ValidationError::InvalidCandidate(WasmInvalidCandidate::AmbiguousWorkerDeath), + ValidationError::InvalidCandidate(WasmInvalidCandidate::HardTimeout), )), validation_data, validation_code, @@ -479,6 +491,122 @@ fn candidate_validation_bad_return_is_invalid() { )) .unwrap(); + assert_matches!(v, ValidationResult::Invalid(InvalidCandidate::Timeout)); +} + +#[test] +fn candidate_validation_one_ambiguous_error_is_valid() { + let validation_data = PersistedValidationData { max_pov_size: 1024, ..Default::default() }; + + let pov = PoV { block_data: BlockData(vec![1; 32]) }; + let head_data = HeadData(vec![1, 1, 1]); + let validation_code = ValidationCode(vec![2; 16]); + + let descriptor = make_valid_candidate_descriptor( + ParaId::from(1_u32), + dummy_hash(), + validation_data.hash(), + pov.hash(), + validation_code.hash(), + head_data.hash(), + dummy_hash(), + Sr25519Keyring::Alice, + ); + + let check = perform_basic_checks( + &descriptor, + validation_data.max_pov_size, + &pov, + &validation_code.hash(), + ); + assert!(check.is_ok()); + + let validation_result = WasmValidationResult { + head_data, + new_validation_code: Some(vec![2, 2, 2].into()), + upward_messages: Vec::new(), + horizontal_messages: Vec::new(), + processed_downward_messages: 0, + hrmp_watermark: 0, + }; + + let commitments = CandidateCommitments { + head_data: validation_result.head_data.clone(), + upward_messages: validation_result.upward_messages.clone(), + horizontal_messages: validation_result.horizontal_messages.clone(), + new_validation_code: validation_result.new_validation_code.clone(), + processed_downward_messages: validation_result.processed_downward_messages, + hrmp_watermark: validation_result.hrmp_watermark, + }; + + let candidate_receipt = CandidateReceipt { descriptor, commitments_hash: commitments.hash() }; + + let v = executor::block_on(validate_candidate_exhaustive( + MockValidateCandidateBackend::with_hardcoded_result_list(vec![ + Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::AmbiguousWorkerDeath)), + Ok(validation_result), + ]), + validation_data.clone(), + validation_code, + candidate_receipt, + Arc::new(pov), + Duration::from_secs(0), + &Default::default(), + )) + .unwrap(); + + assert_matches!(v, ValidationResult::Valid(outputs, used_validation_data) => { + assert_eq!(outputs.head_data, HeadData(vec![1, 1, 1])); + assert_eq!(outputs.upward_messages, Vec::::new()); + assert_eq!(outputs.horizontal_messages, Vec::new()); + assert_eq!(outputs.new_validation_code, Some(vec![2, 2, 2].into())); + assert_eq!(outputs.hrmp_watermark, 0); + assert_eq!(used_validation_data, validation_data); + }); +} + +#[test] +fn candidate_validation_multiple_ambiguous_errors_is_invalid() { + let validation_data = PersistedValidationData { max_pov_size: 1024, ..Default::default() }; + + let pov = PoV { block_data: BlockData(vec![1; 32]) }; + let validation_code = ValidationCode(vec![2; 16]); + + let descriptor = make_valid_candidate_descriptor( + ParaId::from(1_u32), + dummy_hash(), + validation_data.hash(), + pov.hash(), + validation_code.hash(), + dummy_hash(), + dummy_hash(), + Sr25519Keyring::Alice, + ); + + let check = perform_basic_checks( + &descriptor, + validation_data.max_pov_size, + &pov, + &validation_code.hash(), + ); + assert!(check.is_ok()); + + let candidate_receipt = CandidateReceipt { descriptor, commitments_hash: Hash::zero() }; + + let v = executor::block_on(validate_candidate_exhaustive( + MockValidateCandidateBackend::with_hardcoded_result_list(vec![ + Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::AmbiguousWorkerDeath)), + Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::AmbiguousWorkerDeath)), + ]), + validation_data, + validation_code, + candidate_receipt, + Arc::new(pov), + Duration::from_secs(0), + &Default::default(), + )) + .unwrap(); + assert_matches!(v, ValidationResult::Invalid(InvalidCandidate::ExecutionError(_))); } @@ -766,11 +894,11 @@ fn pov_decompression_failure_is_invalid() { } struct MockPreCheckBackend { - result: Result<(), PrepareError>, + result: Result, } impl MockPreCheckBackend { - fn with_hardcoded_result(result: Result<(), PrepareError>) -> Self { + fn with_hardcoded_result(result: Result) -> Self { Self { result } } } @@ -779,14 +907,14 @@ impl MockPreCheckBackend { impl ValidationBackend for MockPreCheckBackend { async fn validate_candidate( &mut self, - _raw_validation_code: Vec, + _pvf: Pvf, _timeout: Duration, - _params: ValidationParams, + _encoded_params: Vec, ) -> Result { unreachable!() } - async fn precheck_pvf(&mut self, _pvf: Pvf) -> Result<(), PrepareError> { + async fn precheck_pvf(&mut self, _pvf: Pvf) -> Result { self.result.clone() } } @@ -803,7 +931,7 @@ fn precheck_works() { let (check_fut, check_result) = precheck_pvf( ctx.sender(), - MockPreCheckBackend::with_hardcoded_result(Ok(())), + MockPreCheckBackend::with_hardcoded_result(Ok(Duration::default())), relay_parent, validation_code_hash, ) @@ -849,7 +977,7 @@ fn precheck_invalid_pvf_blob_compression() { let (check_fut, check_result) = precheck_pvf( ctx.sender(), - MockPreCheckBackend::with_hardcoded_result(Ok(())), + MockPreCheckBackend::with_hardcoded_result(Ok(Duration::default())), relay_parent, validation_code_hash, ) diff --git a/node/core/chain-api/Cargo.toml b/node/core/chain-api/Cargo.toml index ff815a46e646..e51f063c5d1d 100644 --- a/node/core/chain-api/Cargo.toml +++ b/node/core/chain-api/Cargo.toml @@ -1,18 +1,18 @@ [package] name = "polkadot-node-core-chain-api" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" gum = { package = "tracing-gum", path = "../../gum" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-primitives = { path = "../../../primitives" } polkadot-node-subsystem = {path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [dev-dependencies] futures = { version = "0.3.21", features = ["thread-pool"] } @@ -20,4 +20,4 @@ maplit = "1.0.2" parity-scale-codec = "3.1.5" polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } diff --git a/node/core/chain-selection/Cargo.toml b/node/core/chain-selection/Cargo.toml index a1e75625c32e..ce858a87dcd6 100644 --- a/node/core/chain-selection/Cargo.toml +++ b/node/core/chain-selection/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "polkadot-node-core-chain-selection" description = "Chain Selection Subsystem" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -13,13 +13,13 @@ polkadot-primitives = { path = "../../../primitives" } polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } -kvdb = "0.12.0" +kvdb = "0.13.0" thiserror = "1.0.31" parity-scale-codec = "3.1.5" [dev-dependencies] polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } parking_lot = "0.12.0" assert_matches = "1" -kvdb-memorydb = "0.12.0" +kvdb-memorydb = "0.13.0" diff --git a/node/core/chain-selection/src/lib.rs b/node/core/chain-selection/src/lib.rs index eb5ceac9b768..786454fb9891 100644 --- a/node/core/chain-selection/src/lib.rs +++ b/node/core/chain-selection/src/lib.rs @@ -381,6 +381,7 @@ async fn run( ) where B: Backend, { + #![allow(clippy::all)] loop { let res = run_until_error( &mut ctx, @@ -430,7 +431,7 @@ where return Ok(()) } FromOrchestra::Signal(OverseerSignal::ActiveLeaves(update)) => { - for leaf in update.activated { + if let Some(leaf) = update.activated { let write_ops = handle_active_leaf( ctx.sender(), &*backend, diff --git a/node/core/dispute-coordinator/Cargo.toml b/node/core/dispute-coordinator/Cargo.toml index 9c78180baa71..c00e5a597d5e 100644 --- a/node/core/dispute-coordinator/Cargo.toml +++ b/node/core/dispute-coordinator/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "polkadot-node-core-dispute-coordinator" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" gum = { package = "tracing-gum", path = "../../gum" } parity-scale-codec = "3.1.5" -kvdb = "0.12.0" +kvdb = "0.13.0" thiserror = "1.0.31" lru = "0.8.0" fatality = "0.0.6" @@ -18,19 +18,19 @@ polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [dev-dependencies] -kvdb-memorydb = "0.12.0" +kvdb-memorydb = "0.13.0" polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } assert_matches = "1.4.0" test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../../primitives/test-helpers" } futures-timer = "3.0.2" -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] # If not enabled, the dispute coordinator will do nothing. diff --git a/node/core/dispute-coordinator/src/db/v1.rs b/node/core/dispute-coordinator/src/db/v1.rs index 2c643d341de2..ab571108af37 100644 --- a/node/core/dispute-coordinator/src/db/v1.rs +++ b/node/core/dispute-coordinator/src/db/v1.rs @@ -32,7 +32,7 @@ use crate::{ backend::{Backend, BackendWriteOp, OverlayedBackend}, error::{FatalError, FatalResult}, metrics::Metrics, - DISPUTE_WINDOW, LOG_TARGET, + LOG_TARGET, }; const RECENT_DISPUTES_KEY: &[u8; 15] = b"recent-disputes"; @@ -99,10 +99,10 @@ impl DbBackend { encoded = ?candidate_votes_session_prefix(index), "Cleaning votes for session index" ); - tx.delete_prefix(self.config.col_data, &candidate_votes_session_prefix(index)); + tx.delete_prefix(self.config.col_dispute_data, &candidate_votes_session_prefix(index)); } // New watermark: - tx.put_vec(self.config.col_data, CLEANED_VOTES_WATERMARK_KEY, clean_until.encode()); + tx.put_vec(self.config.col_dispute_data, CLEANED_VOTES_WATERMARK_KEY, clean_until.encode()); Ok(()) } } @@ -148,21 +148,32 @@ impl Backend for DbBackend { self.add_vote_cleanup_tx(&mut tx, session)?; // Actually write the earliest session. - tx.put_vec(self.config.col_data, EARLIEST_SESSION_KEY, session.encode()); + tx.put_vec( + self.config.col_dispute_data, + EARLIEST_SESSION_KEY, + session.encode(), + ); }, BackendWriteOp::WriteRecentDisputes(recent_disputes) => { - tx.put_vec(self.config.col_data, RECENT_DISPUTES_KEY, recent_disputes.encode()); + tx.put_vec( + self.config.col_dispute_data, + RECENT_DISPUTES_KEY, + recent_disputes.encode(), + ); }, BackendWriteOp::WriteCandidateVotes(session, candidate_hash, votes) => { gum::trace!(target: LOG_TARGET, ?session, "Writing candidate votes"); tx.put_vec( - self.config.col_data, + self.config.col_dispute_data, &candidate_votes_key(session, &candidate_hash), votes.encode(), ); }, BackendWriteOp::DeleteCandidateVotes(session, candidate_hash) => { - tx.delete(self.config.col_data, &candidate_votes_key(session, &candidate_hash)); + tx.delete( + self.config.col_dispute_data, + &candidate_votes_key(session, &candidate_hash), + ); }, } } @@ -195,7 +206,9 @@ fn candidate_votes_session_prefix(session: SessionIndex) -> [u8; 15 + 4] { #[derive(Debug, Clone)] pub struct ColumnConfiguration { /// The column in the key-value DB where data is stored. - pub col_data: u32, + pub col_dispute_data: u32, + /// The column in the key-value DB where session data is stored. + pub col_session_data: u32, } /// Tracked votes on candidates, for the purposes of dispute resolution. @@ -257,8 +270,12 @@ impl From for crate::error::Error { /// Result alias for DB errors. pub type Result = std::result::Result; -fn load_decode(db: &dyn Database, col_data: u32, key: &[u8]) -> Result> { - match db.get(col_data, key)? { +fn load_decode( + db: &dyn Database, + col_dispute_data: u32, + key: &[u8], +) -> Result> { + match db.get(col_dispute_data, key)? { None => Ok(None), Some(raw) => D::decode(&mut &raw[..]).map(Some).map_err(Into::into), } @@ -271,7 +288,7 @@ pub(crate) fn load_candidate_votes( session: SessionIndex, candidate_hash: &CandidateHash, ) -> SubsystemResult> { - load_decode(db, config.col_data, &candidate_votes_key(session, candidate_hash)) + load_decode(db, config.col_dispute_data, &candidate_votes_key(session, candidate_hash)) .map_err(|e| SubsystemError::with_origin("dispute-coordinator", e)) } @@ -280,7 +297,7 @@ pub(crate) fn load_earliest_session( db: &dyn Database, config: &ColumnConfiguration, ) -> SubsystemResult> { - load_decode(db, config.col_data, EARLIEST_SESSION_KEY) + load_decode(db, config.col_dispute_data, EARLIEST_SESSION_KEY) .map_err(|e| SubsystemError::with_origin("dispute-coordinator", e)) } @@ -289,7 +306,7 @@ pub(crate) fn load_recent_disputes( db: &dyn Database, config: &ColumnConfiguration, ) -> SubsystemResult> { - load_decode(db, config.col_data, RECENT_DISPUTES_KEY) + load_decode(db, config.col_dispute_data, RECENT_DISPUTES_KEY) .map_err(|e| SubsystemError::with_origin("dispute-coordinator", e)) } @@ -301,25 +318,24 @@ pub(crate) fn load_recent_disputes( /// /// If one or more ancient sessions are pruned, all metadata on candidates within the ancient /// session will be deleted. -pub(crate) fn note_current_session( +pub(crate) fn note_earliest_session( overlay_db: &mut OverlayedBackend<'_, impl Backend>, - current_session: SessionIndex, + new_earliest_session: SessionIndex, ) -> SubsystemResult<()> { - let new_earliest = current_session.saturating_sub(DISPUTE_WINDOW.get()); match overlay_db.load_earliest_session()? { None => { // First launch - write new-earliest. - overlay_db.write_earliest_session(new_earliest); + overlay_db.write_earliest_session(new_earliest_session); }, - Some(prev_earliest) if new_earliest > prev_earliest => { + Some(prev_earliest) if new_earliest_session > prev_earliest => { // Prune all data in the outdated sessions. - overlay_db.write_earliest_session(new_earliest); + overlay_db.write_earliest_session(new_earliest_session); // Clear recent disputes metadata. { let mut recent_disputes = overlay_db.load_recent_disputes()?.unwrap_or_default(); - let lower_bound = (new_earliest, CandidateHash(Hash::repeat_byte(0x00))); + 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. @@ -347,7 +363,7 @@ fn load_cleaned_votes_watermark( db: &dyn Database, config: &ColumnConfiguration, ) -> FatalResult> { - load_decode(db, config.col_data, CLEANED_VOTES_WATERMARK_KEY) + load_decode(db, config.col_dispute_data, CLEANED_VOTES_WATERMARK_KEY) .map_err(|e| FatalError::DbReadFailed(e)) } @@ -356,13 +372,14 @@ mod tests { use super::*; use ::test_helpers::{dummy_candidate_receipt, dummy_hash}; + use polkadot_node_primitives::DISPUTE_WINDOW; use polkadot_primitives::v2::{Hash, Id as ParaId}; fn make_db() -> DbBackend { let db = kvdb_memorydb::create(1); let db = polkadot_node_subsystem_util::database::kvdb_impl::DbAdapter::new(db, &[0]); let store = Arc::new(db); - let config = ColumnConfiguration { col_data: 0 }; + let config = ColumnConfiguration { col_dispute_data: 0, col_session_data: 1 }; DbBackend::new(store, config, Metrics::default()) } @@ -405,7 +422,7 @@ mod tests { let mut overlay_db = OverlayedBackend::new(&backend); gum::trace!(target: LOG_TARGET, ?current_session, "Noting current session"); - note_current_session(&mut overlay_db, current_session).unwrap(); + note_earliest_session(&mut overlay_db, earliest_session).unwrap(); let write_ops = overlay_db.into_write_ops(); backend.write(write_ops).unwrap(); @@ -425,7 +442,7 @@ mod tests { let current_session = current_session + 1; let earliest_session = earliest_session + 1; - note_current_session(&mut overlay_db, current_session).unwrap(); + note_earliest_session(&mut overlay_db, earliest_session).unwrap(); let write_ops = overlay_db.into_write_ops(); backend.write(write_ops).unwrap(); @@ -582,7 +599,7 @@ mod tests { } #[test] - fn note_current_session_prunes_old() { + fn note_earliest_session_prunes_old() { let mut backend = make_db(); let hash_a = CandidateHash(Hash::repeat_byte(0x0a)); @@ -631,7 +648,7 @@ mod tests { backend.write(write_ops).unwrap(); let mut overlay_db = OverlayedBackend::new(&backend); - note_current_session(&mut overlay_db, current_session).unwrap(); + note_earliest_session(&mut overlay_db, new_earliest_session).unwrap(); assert_eq!(overlay_db.load_earliest_session().unwrap(), Some(new_earliest_session)); diff --git a/node/core/dispute-coordinator/src/import.rs b/node/core/dispute-coordinator/src/import.rs index 020d04792191..84adae167c7a 100644 --- a/node/core/dispute-coordinator/src/import.rs +++ b/node/core/dispute-coordinator/src/import.rs @@ -28,11 +28,13 @@ use std::collections::{BTreeMap, HashMap, HashSet}; -use polkadot_node_primitives::{CandidateVotes, SignedDisputeStatement}; +use polkadot_node_primitives::{ + disputes::ValidCandidateVotes, CandidateVotes, DisputeStatus, SignedDisputeStatement, Timestamp, +}; use polkadot_node_subsystem_util::rolling_session_window::RollingSessionWindow; use polkadot_primitives::v2::{ - CandidateReceipt, DisputeStatement, SessionIndex, SessionInfo, ValidDisputeStatementKind, - ValidatorId, ValidatorIndex, ValidatorPair, ValidatorSignature, + CandidateReceipt, DisputeStatement, IndexedVec, SessionIndex, SessionInfo, + ValidDisputeStatementKind, ValidatorId, ValidatorIndex, ValidatorPair, ValidatorSignature, }; use sc_keystore::LocalKeystore; @@ -63,7 +65,7 @@ impl<'a> CandidateEnvironment<'a> { } /// Validators in the candidate's session. - pub fn validators(&self) -> &Vec { + pub fn validators(&self) -> &IndexedVec { &self.session.validators } @@ -101,7 +103,7 @@ impl OwnVoteState { let mut our_valid_votes = env .controlled_indices() .iter() - .filter_map(|i| votes.valid.get_key_value(i)) + .filter_map(|i| votes.valid.raw().get_key_value(i)) .peekable(); let mut our_invalid_votes = env.controlled_indices.iter().filter_map(|i| votes.invalid.get_key_value(i)); @@ -154,22 +156,8 @@ pub struct CandidateVoteState { /// Information about own votes: own_vote: OwnVoteState, - /// Whether or not the dispute concluded invalid. - concluded_invalid: bool, - - /// Whether or not the dispute concluded valid. - /// - /// Note: Due to equivocations it is technically possible for a dispute to conclude both valid - /// and invalid. In that case the invalid result takes precedence. - concluded_valid: bool, - - /// There is an ongoing dispute and we reached f+1 votes -> the dispute is confirmed - /// - /// as at least one honest validator cast a vote for the candidate. - is_confirmed: bool, - - /// Whether or not we have an ongoing dispute. - is_disputed: bool, + /// Current dispute status, if there is any. + dispute_status: Option, } impl CandidateVoteState { @@ -177,20 +165,16 @@ impl CandidateVoteState { /// /// in case there have not been any previous votes. pub fn new_from_receipt(candidate_receipt: CandidateReceipt) -> Self { - let votes = - CandidateVotes { candidate_receipt, valid: BTreeMap::new(), invalid: BTreeMap::new() }; - Self { - votes, - own_vote: OwnVoteState::NoVote, - concluded_invalid: false, - concluded_valid: false, - is_confirmed: false, - is_disputed: false, - } + let votes = CandidateVotes { + candidate_receipt, + valid: ValidCandidateVotes::new(), + invalid: BTreeMap::new(), + }; + Self { votes, own_vote: OwnVoteState::NoVote, dispute_status: None } } /// Create a new `CandidateVoteState` from already existing votes. - pub fn new<'a>(votes: CandidateVotes, env: &CandidateEnvironment<'a>) -> Self { + pub fn new(votes: CandidateVotes, env: &CandidateEnvironment, now: Timestamp) -> Self { let own_vote = OwnVoteState::new(&votes, env); let n_validators = env.validators().len(); @@ -198,16 +182,31 @@ impl CandidateVoteState { let supermajority_threshold = polkadot_primitives::v2::supermajority_threshold(n_validators); - let concluded_invalid = votes.invalid.len() >= supermajority_threshold; - let concluded_valid = votes.valid.len() >= supermajority_threshold; - // We have a dispute, if we have votes on both sides: - let is_disputed = !votes.invalid.is_empty() && !votes.valid.is_empty(); - - let byzantine_threshold = polkadot_primitives::v2::byzantine_threshold(n_validators); - let is_confirmed = votes.voted_indices().len() > byzantine_threshold && is_disputed; + let is_disputed = !votes.invalid.is_empty() && !votes.valid.raw().is_empty(); + + let dispute_status = if is_disputed { + let mut status = DisputeStatus::active(); + let byzantine_threshold = polkadot_primitives::v2::byzantine_threshold(n_validators); + let is_confirmed = votes.voted_indices().len() > byzantine_threshold; + if is_confirmed { + status = status.confirm(); + }; + let concluded_for = votes.valid.raw().len() >= supermajority_threshold; + if concluded_for { + status = status.conclude_for(now); + }; + + let concluded_against = votes.invalid.len() >= supermajority_threshold; + if concluded_against { + status = status.conclude_against(now); + }; + Some(status) + } else { + None + }; - Self { votes, own_vote, concluded_invalid, concluded_valid, is_confirmed, is_disputed } + Self { votes, own_vote, dispute_status } } /// Import fresh statements. @@ -217,6 +216,7 @@ impl CandidateVoteState { self, env: &CandidateEnvironment, statements: Vec<(SignedDisputeStatement, ValidatorIndex)>, + now: Timestamp, ) -> ImportResult { let (mut votes, old_state) = self.into_old_state(); @@ -229,7 +229,7 @@ impl CandidateVoteState { for (statement, val_index) in statements { if env .validators() - .get(val_index.0 as usize) + .get(val_index) .map_or(true, |v| v != statement.validator_public()) { gum::error!( @@ -267,25 +267,20 @@ impl CandidateVoteState { match statement.statement() { DisputeStatement::Valid(valid_kind) => { - let fresh = insert_into_statements( - &mut votes.valid, - *valid_kind, + let fresh = votes.valid.insert_vote( val_index, + *valid_kind, statement.into_validator_signature(), ); - if fresh { imported_valid_votes += 1; } }, DisputeStatement::Invalid(invalid_kind) => { - let fresh = insert_into_statements( - &mut votes.invalid, - *invalid_kind, - val_index, - statement.into_validator_signature(), - ); - + let fresh = votes + .invalid + .insert(val_index, (*invalid_kind, statement.into_validator_signature())) + .is_none(); if fresh { new_invalid_voters.push(val_index); imported_invalid_votes += 1; @@ -294,7 +289,7 @@ impl CandidateVoteState { } } - let new_state = Self::new(votes, env); + let new_state = Self::new(votes, env, now); ImportResult { old_state, @@ -313,32 +308,15 @@ impl CandidateVoteState { /// Extract `CandidateVotes` for handling import of new statements. fn into_old_state(self) -> (CandidateVotes, CandidateVoteState<()>) { - let CandidateVoteState { - votes, - own_vote, - concluded_invalid, - concluded_valid, - is_confirmed, - is_disputed, - } = self; - ( - votes, - CandidateVoteState { - votes: (), - own_vote, - concluded_invalid, - concluded_valid, - is_confirmed, - is_disputed, - }, - ) + let CandidateVoteState { votes, own_vote, dispute_status } = self; + (votes, CandidateVoteState { votes: (), own_vote, dispute_status }) } } impl CandidateVoteState { /// Whether or not we have an ongoing dispute. pub fn is_disputed(&self) -> bool { - self.is_disputed + self.dispute_status.is_some() } /// Whether there is an ongoing confirmed dispute. @@ -346,7 +324,7 @@ impl CandidateVoteState { /// This checks whether there is a dispute ongoing and we have more than byzantine threshold /// votes. pub fn is_confirmed(&self) -> bool { - self.is_confirmed + self.dispute_status.map_or(false, |s| s.is_confirmed_concluded()) } /// This machine already cast some vote in that dispute/for that candidate. @@ -359,14 +337,19 @@ impl CandidateVoteState { self.own_vote.approval_votes() } - /// Whether or not this dispute has already enough valid votes to conclude. - pub fn is_concluded_valid(&self) -> bool { - self.concluded_valid + /// Whether or not there is a dispute and it has already enough valid votes to conclude. + pub fn has_concluded_for(&self) -> bool { + self.dispute_status.map_or(false, |s| s.has_concluded_for()) + } + + /// Whether or not there is a dispute and it has already enough invalid votes to conclude. + pub fn has_concluded_against(&self) -> bool { + self.dispute_status.map_or(false, |s| s.has_concluded_against()) } - /// Whether or not this dispute has already enough invalid votes to conclude. - pub fn is_concluded_invalid(&self) -> bool { - self.concluded_invalid + /// Get access to the dispute status, in case there is one. + pub fn dispute_status(&self) -> &Option { + &self.dispute_status } /// Access to underlying votes. @@ -451,18 +434,18 @@ impl ImportResult { } /// Whether or not any dispute just concluded valid due to the import. - pub fn is_freshly_concluded_valid(&self) -> bool { - !self.old_state().is_concluded_valid() && self.new_state().is_concluded_valid() + pub fn is_freshly_concluded_for(&self) -> bool { + !self.old_state().has_concluded_for() && self.new_state().has_concluded_for() } /// Whether or not any dispute just concluded invalid due to the import. - pub fn is_freshly_concluded_invalid(&self) -> bool { - !self.old_state().is_concluded_invalid() && self.new_state().is_concluded_invalid() + pub fn is_freshly_concluded_against(&self) -> bool { + !self.old_state().has_concluded_against() && self.new_state().has_concluded_against() } /// Whether or not any dispute just concluded either invalid or valid due to the import. pub fn is_freshly_concluded(&self) -> bool { - self.is_freshly_concluded_invalid() || self.is_freshly_concluded_valid() + self.is_freshly_concluded_against() || self.is_freshly_concluded_for() } /// Modify this `ImportResult`s, by importing additional approval votes. @@ -473,6 +456,7 @@ impl ImportResult { self, env: &CandidateEnvironment, approval_votes: HashMap, + now: Timestamp, ) -> Self { let Self { old_state, @@ -488,7 +472,7 @@ impl ImportResult { for (index, sig) in approval_votes.into_iter() { debug_assert!( { - let pub_key = &env.session_info().validators[index.0 as usize]; + let pub_key = &env.session_info().validators.get(index).expect("indices are validated by approval-voting subsystem; qed"); let candidate_hash = votes.candidate_receipt.hash(); let session_index = env.session_index(); DisputeStatement::Valid(ValidDisputeStatementKind::ApprovalChecking) @@ -497,18 +481,13 @@ impl ImportResult { }, "Signature check for imported approval votes failed! This is a serious bug. Session: {:?}, candidate hash: {:?}, validator index: {:?}", env.session_index(), votes.candidate_receipt.hash(), index ); - if insert_into_statements( - &mut votes.valid, - ValidDisputeStatementKind::ApprovalChecking, - index, - sig, - ) { + if votes.valid.insert_vote(index, ValidDisputeStatementKind::ApprovalChecking, sig) { imported_valid_votes += 1; imported_approval_votes += 1; } } - let new_state = CandidateVoteState::new(votes, env); + let new_state = CandidateVoteState::new(votes, env, now); Self { old_state, @@ -538,7 +517,7 @@ impl ImportResult { /// That is all `ValidatorIndex`es we have private keys for. Usually this will only be one. fn find_controlled_validator_indices( keystore: &LocalKeystore, - validators: &[ValidatorId], + validators: &IndexedVec, ) -> HashSet { let mut controlled = HashSet::new(); for (index, validator) in validators.iter().enumerate() { @@ -551,14 +530,3 @@ fn find_controlled_validator_indices( controlled } - -// Returns 'true' if no other vote by that validator was already -// present and 'false' otherwise. Same semantics as `HashSet`. -fn insert_into_statements( - m: &mut BTreeMap, - tag: T, - val_index: ValidatorIndex, - val_signature: ValidatorSignature, -) -> bool { - m.insert(val_index, (tag, val_signature)).is_none() -} diff --git a/node/core/dispute-coordinator/src/initialized.rs b/node/core/dispute-coordinator/src/initialized.rs index 5f29245f33f8..245af523685f 100644 --- a/node/core/dispute-coordinator/src/initialized.rs +++ b/node/core/dispute-coordinator/src/initialized.rs @@ -26,8 +26,8 @@ use futures::{ use sc_keystore::LocalKeystore; use polkadot_node_primitives::{ - CandidateVotes, DisputeMessage, DisputeMessageCheckError, DisputeStatus, - SignedDisputeStatement, Timestamp, DISPUTE_WINDOW, + disputes::ValidCandidateVotes, CandidateVotes, DisputeMessage, DisputeMessageCheckError, + DisputeStatus, SignedDisputeStatement, Timestamp, }; use polkadot_node_subsystem::{ messages::{ @@ -299,7 +299,7 @@ impl Initialized { self.highest_session = session; - db::v1::note_current_session(overlay_db, session)?; + db::v1::note_earliest_session(overlay_db, new_window_start)?; self.spam_slots.prune_old(new_window_start); } }, @@ -372,7 +372,7 @@ impl Initialized { .filter_map(|(validator_index, attestation)| { let validator_public: ValidatorId = session_info .validators - .get(validator_index.0 as usize) + .get(validator_index) .or_else(|| { gum::error!( target: LOG_TARGET, @@ -473,7 +473,7 @@ impl Initialized { let validator_public: ValidatorId = session_info .validators - .get(validator_index.0 as usize) + .get(validator_index) .or_else(|| { gum::error!( target: LOG_TARGET, @@ -617,7 +617,9 @@ impl Initialized { let _ = tx.send( get_active_with_status(recent_disputes.into_iter(), now) - .map(|(k, _)| k) + .map(|((session_idx, candidate_hash), dispute_status)| { + (session_idx, candidate_hash, dispute_status) + }) .collect(), ); }, @@ -706,25 +708,27 @@ impl Initialized { now: Timestamp, ) -> Result { gum::trace!(target: LOG_TARGET, ?statements, "In handle import statements"); - if session + DISPUTE_WINDOW.get() < self.highest_session { - // It is not valid to participate in an ancient dispute (spam?). + if !self.rolling_session_window.contains(session) { + // It is not valid to participate in an ancient dispute (spam?) or too new. return Ok(ImportStatementsResult::InvalidImport) } - let env = - match CandidateEnvironment::new(&*self.keystore, &self.rolling_session_window, session) - { - None => { - gum::warn!( - target: LOG_TARGET, - session, - "We are lacking a `SessionInfo` for handling import of statements." - ); + let env = match CandidateEnvironment::new( + &self.keystore, + &self.rolling_session_window, + session, + ) { + None => { + gum::warn!( + target: LOG_TARGET, + session, + "We are lacking a `SessionInfo` for handling import of statements." + ); - return Ok(ImportStatementsResult::InvalidImport) - }, - Some(env) => env, - }; + return Ok(ImportStatementsResult::InvalidImport) + }, + Some(env) => env, + }; let candidate_hash = candidate_receipt.hash(); @@ -748,7 +752,7 @@ impl Initialized { .load_candidate_votes(session, &candidate_hash)? .map(CandidateVotes::from) { - Some(votes) => CandidateVoteState::new(votes, &env), + Some(votes) => CandidateVoteState::new(votes, &env, now), None => if let MaybeCandidateReceipt::Provides(candidate_receipt) = candidate_receipt { CandidateVoteState::new_from_receipt(candidate_receipt) @@ -766,7 +770,7 @@ impl Initialized { gum::trace!(target: LOG_TARGET, ?candidate_hash, ?session, "Loaded votes"); let import_result = { - let intermediate_result = old_state.import_statements(&env, statements); + let intermediate_result = old_state.import_statements(&env, statements, now); // Handle approval vote import: // @@ -803,7 +807,14 @@ impl Initialized { ); intermediate_result }, - Ok(votes) => intermediate_result.import_approval_votes(&env, votes), + Ok(votes) => { + gum::trace!( + target: LOG_TARGET, + count = votes.len(), + "Successfully received approval votes." + ); + intermediate_result.import_approval_votes(&env, votes, now) + }, } } else { gum::trace!( @@ -869,12 +880,21 @@ impl Initialized { } } + let has_own_vote = new_state.has_own_vote(); + let is_disputed = new_state.is_disputed(); + let has_controlled_indices = !env.controlled_indices().is_empty(); + let is_backed = self.scraper.is_candidate_backed(&candidate_hash); + let is_confirmed = new_state.is_confirmed(); + // We participate only in disputes which are included, backed or confirmed + let allow_participation = is_included || is_backed || is_confirmed; + // Participate in dispute if we did not cast a vote before and actually have keys to cast a - // local vote: - if !new_state.has_own_vote() && - new_state.is_disputed() && - !env.controlled_indices().is_empty() - { + // local vote. Disputes should fall in one of the categories below, otherwise we will refrain + // from participation: + // - `is_included` lands in prioritised queue + // - `is_confirmed` | `is_backed` lands in best effort queue + // We don't participate in disputes on finalized candidates. + if !has_own_vote && is_disputed && has_controlled_indices && allow_participation { let priority = ParticipationPriority::with_priority_if(is_included); gum::trace!( target: LOG_TARGET, @@ -896,6 +916,23 @@ impl Initialized { ) .await; log_error(r)?; + } else { + gum::trace!( + target: LOG_TARGET, + ?candidate_hash, + ?is_confirmed, + ?has_own_vote, + ?is_disputed, + ?has_controlled_indices, + ?allow_participation, + ?is_included, + ?is_backed, + "Will not queue participation for candidate" + ); + + if !allow_participation { + self.metrics.on_refrained_participation(); + } } // Also send any already existing approval vote on new disputes: @@ -903,7 +940,7 @@ impl Initialized { let no_votes = Vec::new(); let our_approval_votes = new_state.own_approval_votes().unwrap_or(&no_votes); for (validator_index, sig) in our_approval_votes { - let pub_key = match env.validators().get(validator_index.0 as usize) { + let pub_key = match env.validators().get(*validator_index) { None => { gum::error!( target: LOG_TARGET, @@ -951,43 +988,34 @@ impl Initialized { } // All good, update recent disputes if state has changed: - if import_result.dispute_state_changed() { - let mut recent_disputes = overlay_db.load_recent_disputes()?.unwrap_or_default(); + if let Some(new_status) = new_state.dispute_status() { + // Only bother with db access, if there was an actual change. + if import_result.dispute_state_changed() { + let mut recent_disputes = overlay_db.load_recent_disputes()?.unwrap_or_default(); + + let status = + recent_disputes.entry((session, candidate_hash)).or_insert_with(|| { + gum::info!( + target: LOG_TARGET, + ?candidate_hash, + session, + "New dispute initiated for candidate.", + ); + DisputeStatus::active() + }); + + *status = *new_status; - let status = recent_disputes.entry((session, candidate_hash)).or_insert_with(|| { - gum::info!( + gum::trace!( target: LOG_TARGET, ?candidate_hash, - session, - "New dispute initiated for candidate.", + ?status, + has_concluded_for = ?new_state.has_concluded_for(), + has_concluded_against = ?new_state.has_concluded_against(), + "Writing recent disputes with updates for candidate" ); - DisputeStatus::active() - }); - - if new_state.is_confirmed() { - *status = status.confirm(); - } - - // Note: concluded-invalid overwrites concluded-valid, - // so we do this check first. Dispute state machine is - // non-commutative. - if new_state.is_concluded_valid() { - *status = status.concluded_for(now); + overlay_db.write_recent_disputes(recent_disputes); } - - if new_state.is_concluded_invalid() { - *status = status.concluded_against(now); - } - - gum::trace!( - target: LOG_TARGET, - ?candidate_hash, - ?status, - is_concluded_valid = ?new_state.is_concluded_valid(), - is_concluded_invalid = ?new_state.is_concluded_invalid(), - "Writing recent disputes with updates for candidate" - ); - overlay_db.write_recent_disputes(recent_disputes); } // Update metrics: @@ -1003,14 +1031,14 @@ impl Initialized { imported_approval_votes = ?import_result.imported_approval_votes(), imported_valid_votes = ?import_result.imported_valid_votes(), imported_invalid_votes = ?import_result.imported_invalid_votes(), - total_valid_votes = ?import_result.new_state().votes().valid.len(), + total_valid_votes = ?import_result.new_state().votes().valid.raw().len(), total_invalid_votes = ?import_result.new_state().votes().invalid.len(), confirmed = ?import_result.new_state().is_confirmed(), "Import summary" ); self.metrics.on_approval_votes(import_result.imported_approval_votes()); - if import_result.is_freshly_concluded_valid() { + if import_result.is_freshly_concluded_for() { gum::info!( target: LOG_TARGET, ?candidate_hash, @@ -1019,7 +1047,7 @@ impl Initialized { ); self.metrics.on_concluded_valid(); } - if import_result.is_freshly_concluded_invalid() { + if import_result.is_freshly_concluded_against() { gum::info!( target: LOG_TARGET, ?candidate_hash, @@ -1056,27 +1084,29 @@ impl Initialized { "Issuing local statement for candidate!" ); // Load environment: - let env = - match CandidateEnvironment::new(&*self.keystore, &self.rolling_session_window, session) - { - None => { - gum::warn!( - target: LOG_TARGET, - session, - "Missing info for session which has an active dispute", - ); + let env = match CandidateEnvironment::new( + &self.keystore, + &self.rolling_session_window, + session, + ) { + None => { + gum::warn!( + target: LOG_TARGET, + session, + "Missing info for session which has an active dispute", + ); - return Ok(()) - }, - Some(env) => env, - }; + return Ok(()) + }, + Some(env) => env, + }; let votes = overlay_db .load_candidate_votes(session, &candidate_hash)? .map(CandidateVotes::from) .unwrap_or_else(|| CandidateVotes { candidate_receipt: candidate_receipt.clone(), - valid: BTreeMap::new(), + valid: ValidCandidateVotes::new(), invalid: BTreeMap::new(), }); @@ -1097,7 +1127,10 @@ impl Initialized { valid, candidate_hash, session, - env.validators()[index.0 as usize].clone(), + env.validators() + .get(*index) + .expect("`controlled_indices` are derived from `validators`; qed") + .clone(), ) .await; @@ -1235,10 +1268,10 @@ fn make_dispute_message( votes.invalid.iter().next().ok_or(DisputeMessageCreationError::NoOppositeVote)?; let other_vote = SignedDisputeStatement::new_checked( DisputeStatement::Invalid(*statement_kind), - our_vote.candidate_hash().clone(), + *our_vote.candidate_hash(), our_vote.session_index(), validators - .get(validator_index.0 as usize) + .get(*validator_index) .ok_or(DisputeMessageCreationError::InvalidValidatorIndex)? .clone(), validator_signature.clone(), @@ -1246,14 +1279,18 @@ fn make_dispute_message( .map_err(|()| DisputeMessageCreationError::InvalidStoredStatement)?; (our_vote, our_index, other_vote, *validator_index) } else { - let (validator_index, (statement_kind, validator_signature)) = - votes.valid.iter().next().ok_or(DisputeMessageCreationError::NoOppositeVote)?; + let (validator_index, (statement_kind, validator_signature)) = votes + .valid + .raw() + .iter() + .next() + .ok_or(DisputeMessageCreationError::NoOppositeVote)?; let other_vote = SignedDisputeStatement::new_checked( DisputeStatement::Valid(*statement_kind), - our_vote.candidate_hash().clone(), + *our_vote.candidate_hash(), our_vote.session_index(), validators - .get(validator_index.0 as usize) + .get(*validator_index) .ok_or(DisputeMessageCreationError::InvalidValidatorIndex)? .clone(), validator_signature.clone(), diff --git a/node/core/dispute-coordinator/src/lib.rs b/node/core/dispute-coordinator/src/lib.rs index 6289eb2f11a2..e7ac66ce2ece 100644 --- a/node/core/dispute-coordinator/src/lib.rs +++ b/node/core/dispute-coordinator/src/lib.rs @@ -30,12 +30,13 @@ use futures::FutureExt; use sc_keystore::LocalKeystore; -use polkadot_node_primitives::{CandidateVotes, DISPUTE_WINDOW}; +use polkadot_node_primitives::CandidateVotes; use polkadot_node_subsystem::{ overseer, ActivatedLeaf, FromOrchestra, OverseerSignal, SpawnedSubsystem, SubsystemError, }; use polkadot_node_subsystem_util::{ - database::Database, rolling_session_window::RollingSessionWindow, + database::Database, + rolling_session_window::{DatabaseParams, RollingSessionWindow}, }; use polkadot_primitives::v2::{ScrapedOnChainVotes, ValidatorIndex, ValidatorPair}; @@ -117,12 +118,17 @@ pub struct DisputeCoordinatorSubsystem { #[derive(Debug, Clone, Copy)] pub struct Config { /// The data column in the store to use for dispute data. - pub col_data: u32, + pub col_dispute_data: u32, + /// The data column in the store to use for session data. + pub col_session_data: u32, } impl Config { fn column_config(&self) -> db::v1::ColumnConfiguration { - db::v1::ColumnConfiguration { col_data: self.col_data } + db::v1::ColumnConfiguration { + col_dispute_data: self.col_dispute_data, + col_session_data: self.col_session_data, + } } } @@ -199,17 +205,21 @@ impl DisputeCoordinatorSubsystem { B: Backend + 'static, { loop { - let (first_leaf, rolling_session_window) = match get_rolling_session_window(ctx).await { - Ok(Some(update)) => update, - Ok(None) => { - gum::info!(target: LOG_TARGET, "received `Conclude` signal, exiting"); - return Ok(None) - }, - Err(e) => { - e.split()?.log(); - continue - }, - }; + let db_params = + DatabaseParams { db: self.store.clone(), db_column: self.config.col_session_data }; + + let (first_leaf, rolling_session_window) = + match get_rolling_session_window(ctx, db_params).await { + Ok(Some(update)) => update, + Ok(None) => { + gum::info!(target: LOG_TARGET, "received `Conclude` signal, exiting"); + return Ok(None) + }, + Err(e) => { + e.split()?.log(); + continue + }, + }; let mut overlay_db = OverlayedBackend::new(&mut backend); let (participations, votes, spam_slots, ordering_provider) = match self @@ -262,7 +272,7 @@ impl DisputeCoordinatorSubsystem { ChainScraper, )> { // Prune obsolete disputes: - db::v1::note_current_session(overlay_db, rolling_session_window.latest_session())?; + db::v1::note_earliest_session(overlay_db, rolling_session_window.earliest_session())?; let active_disputes = match overlay_db.load_recent_disputes() { Ok(Some(disputes)) => @@ -276,7 +286,7 @@ impl DisputeCoordinatorSubsystem { let mut participation_requests = Vec::new(); let mut unconfirmed_disputes: UnconfirmedDisputes = UnconfirmedDisputes::new(); - let (mut scraper, votes) = ChainScraper::new(ctx.sender(), initial_head).await?; + let (scraper, votes) = ChainScraper::new(ctx.sender(), initial_head).await?; for ((session, ref candidate_hash), status) in active_disputes { let votes: CandidateVotes = match overlay_db.load_candidate_votes(session, candidate_hash) { @@ -352,12 +362,13 @@ impl DisputeCoordinatorSubsystem { #[overseer::contextbounds(DisputeCoordinator, prefix = self::overseer)] async fn get_rolling_session_window( ctx: &mut Context, + db_params: DatabaseParams, ) -> Result> { if let Some(leaf) = { wait_for_first_leaf(ctx) }.await? { let sender = ctx.sender().clone(); Ok(Some(( leaf.clone(), - RollingSessionWindow::new(sender, DISPUTE_WINDOW, leaf.hash) + RollingSessionWindow::new(sender, leaf.hash, db_params) .await .map_err(JfyiError::RollingSessionWindow)?, ))) diff --git a/node/core/dispute-coordinator/src/metrics.rs b/node/core/dispute-coordinator/src/metrics.rs index 1fbe7e49e8b8..70cd49ac49d1 100644 --- a/node/core/dispute-coordinator/src/metrics.rs +++ b/node/core/dispute-coordinator/src/metrics.rs @@ -30,6 +30,8 @@ struct MetricsInner { queued_participations: prometheus::CounterVec, /// How long vote cleanup batches take. vote_cleanup_time: prometheus::Histogram, + /// Number of refrained participations. + refrained_participations: prometheus::Counter, } /// Candidate validation metrics. @@ -88,6 +90,12 @@ impl Metrics { pub(crate) fn time_vote_cleanup(&self) -> Option { self.0.as_ref().map(|metrics| metrics.vote_cleanup_time.start_timer()) } + + pub(crate) fn on_refrained_participation(&self) { + if let Some(metrics) = &self.0 { + metrics.refrained_participations.inc(); + } + } } impl metrics::Metrics for Metrics { @@ -147,6 +155,14 @@ impl metrics::Metrics for Metrics { )?, registry, )?, + refrained_participations: prometheus::register( + prometheus::Counter::with_opts( + prometheus::Opts::new( + "polkadot_parachain_dispute_refrained_participations", + "Number of refrained participations. We refrain from participation if all of the following conditions are met: disputed candidate is not included, not backed and not confirmed.", + ))?, + registry, + )?, }; Ok(Metrics(Some(metrics))) } diff --git a/node/core/dispute-coordinator/src/participation/mod.rs b/node/core/dispute-coordinator/src/participation/mod.rs index 874f37e63213..e923e13e8142 100644 --- a/node/core/dispute-coordinator/src/participation/mod.rs +++ b/node/core/dispute-coordinator/src/participation/mod.rs @@ -235,7 +235,7 @@ impl Participation { req: ParticipationRequest, recent_head: Hash, ) -> FatalResult<()> { - if self.running_participations.insert(req.candidate_hash().clone()) { + if self.running_participations.insert(*req.candidate_hash()) { let sender = ctx.sender().clone(); ctx.spawn( "participation-worker", diff --git a/node/core/dispute-coordinator/src/participation/queues/mod.rs b/node/core/dispute-coordinator/src/participation/queues/mod.rs index 3ec217628625..29380bd77df1 100644 --- a/node/core/dispute-coordinator/src/participation/queues/mod.rs +++ b/node/core/dispute-coordinator/src/participation/queues/mod.rs @@ -14,10 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use std::{ - cmp::Ordering, - collections::{BTreeMap, HashMap}, -}; +use std::{cmp::Ordering, collections::BTreeMap}; use futures::channel::oneshot; use polkadot_node_subsystem::{messages::ChainApiMessage, overseer}; @@ -50,25 +47,14 @@ const PRIORITY_QUEUE_SIZE: usize = 20_000; #[cfg(test)] const PRIORITY_QUEUE_SIZE: usize = 2; -/// Type for counting how often a candidate was added to the best effort queue. -type BestEffortCount = u32; - /// Queues for dispute participation. +/// In both queues we have a strict ordering of candidates and participation will +/// happen in that order. Refer to `CandidateComparator` for details on the ordering. pub struct Queues { /// Set of best effort participation requests. - /// - /// Note that as size is limited to `BEST_EFFORT_QUEUE_SIZE` we simply do a linear search for - /// the entry with the highest `added_count` to determine what dispute to participate next in. - /// - /// This mechanism leads to an amplifying effect - the more validators already participated, - /// the more likely it becomes that more validators will participate soon, which should lead to - /// a quick resolution of disputes, even in the best effort queue. - best_effort: HashMap, + best_effort: BTreeMap, /// Priority queue. - /// - /// In the priority queue, we have a strict ordering of candidates and participation will - /// happen in that order. priority: BTreeMap, } @@ -143,14 +129,13 @@ impl ParticipationRequest { impl Queues { /// Create new `Queues`. pub fn new() -> Self { - Self { best_effort: HashMap::new(), priority: BTreeMap::new() } + Self { best_effort: BTreeMap::new(), priority: BTreeMap::new() } } /// Will put message in queue, either priority or best effort depending on priority. /// /// If the message was already previously present on best effort, it will be moved to priority - /// if it considered priority now, otherwise the `added_count` on the best effort queue will be - /// bumped. + /// if it is considered priority now. /// /// Returns error in case a queue was found full already. pub async fn queue( @@ -159,94 +144,76 @@ impl Queues { priority: ParticipationPriority, req: ParticipationRequest, ) -> Result<()> { - let comparator = match priority { - ParticipationPriority::BestEffort => None, - ParticipationPriority::Priority => - CandidateComparator::new(sender, &req.candidate_receipt).await?, - }; - self.queue_with_comparator(comparator, req)?; + let comparator = CandidateComparator::new(sender, &req.candidate_receipt).await?; + + self.queue_with_comparator(comparator, priority, req)?; Ok(()) } - /// Get the next best request for dispute participation - /// - /// if any. Priority queue is always considered first, then the best effort queue based on - /// `added_count`. + /// Get the next best request for dispute participation if any. + /// First the priority queue is considered and then the best effort one. pub fn dequeue(&mut self) -> Option { if let Some(req) = self.pop_priority() { - // In case a candidate became best effort over time, we might have it also queued in - // the best effort queue - get rid of any such entry: - self.best_effort.remove(req.candidate_hash()); - return Some(req) + return Some(req.1) } - self.pop_best_effort() + self.pop_best_effort().map(|d| d.1) } fn queue_with_comparator( &mut self, - comparator: Option, + comparator: CandidateComparator, + priority: ParticipationPriority, req: ParticipationRequest, ) -> std::result::Result<(), QueueError> { - if let Some(comparator) = comparator { + if priority.is_priority() { if self.priority.len() >= PRIORITY_QUEUE_SIZE { return Err(QueueError::PriorityFull) } // Remove any best effort entry: - self.best_effort.remove(&req.candidate_hash); + self.best_effort.remove(&comparator); self.priority.insert(comparator, req); } else { + if self.priority.contains_key(&comparator) { + // The candidate is already in priority queue - don't + // add in in best effort too. + return Ok(()) + } if self.best_effort.len() >= BEST_EFFORT_QUEUE_SIZE { return Err(QueueError::BestEffortFull) } - // Note: The request might have been added to priority in a previous call already, we - // take care of that case in `dequeue` (more efficient). - self.best_effort - .entry(req.candidate_hash) - .or_insert(BestEffortEntry { req, added_count: 0 }) - .added_count += 1; + self.best_effort.insert(comparator, req); } Ok(()) } - /// Get the next best from the best effort queue. - /// - /// If there are multiple best - just pick one. - fn pop_best_effort(&mut self) -> Option { - let best = self.best_effort.iter().reduce(|(hash1, entry1), (hash2, entry2)| { - if entry1.added_count > entry2.added_count { - (hash1, entry1) - } else { - (hash2, entry2) - } - }); - if let Some((best_hash, _)) = best { - let best_hash = best_hash.clone(); - self.best_effort.remove(&best_hash).map(|e| e.req) - } else { - None - } + /// Get best from the best effort queue. + fn pop_best_effort(&mut self) -> Option<(CandidateComparator, ParticipationRequest)> { + return Self::pop_impl(&mut self.best_effort) } /// Get best priority queue entry. - fn pop_priority(&mut self) -> Option { + fn pop_priority(&mut self) -> Option<(CandidateComparator, ParticipationRequest)> { + return Self::pop_impl(&mut self.priority) + } + + // `pop_best_effort` and `pop_priority` do the same but on different `BTreeMap`s. This function has + // the extracted implementation + fn pop_impl( + target: &mut BTreeMap, + ) -> Option<(CandidateComparator, ParticipationRequest)> { // Once https://github.com/rust-lang/rust/issues/62924 is there, we can use a simple: - // priority.pop_first(). - if let Some((comparator, _)) = self.priority.iter().next() { - let comparator = comparator.clone(); - self.priority.remove(&comparator) + // target.pop_first(). + if let Some((comparator, _)) = target.iter().next() { + let comparator = *comparator; + target + .remove(&comparator) + .map(|participation_request| (comparator, participation_request)) } else { None } } } -/// Entry for the best effort queue. -struct BestEffortEntry { - req: ParticipationRequest, - /// How often was the above request added to the queue. - added_count: BestEffortCount, -} - /// `Comparator` for ordering of disputes for candidates. /// /// This `comparator` makes it possible to order disputes based on age and to ensure some fairness @@ -266,9 +233,12 @@ struct BestEffortEntry { #[derive(Copy, Clone)] #[cfg_attr(test, derive(Debug))] struct CandidateComparator { - /// Block number of the relay parent. + /// Block number of the relay parent. It's wrapped in an `Option<>` because there are cases when + /// it can't be obtained. For example when the node is lagging behind and new leaves are received + /// with a slight delay. Candidates with unknown relay parent are treated with the lowest priority. /// - /// Important, so we will be participating in oldest disputes first. + /// The order enforced by `CandidateComparator` is important because we want to participate in + /// the oldest disputes first. /// /// Note: In theory it would make more sense to use the `BlockNumber` of the including /// block, as inclusion time is the actual relevant event when it comes to ordering. The @@ -277,8 +247,10 @@ struct CandidateComparator { /// just using the lowest `BlockNumber` of all available including blocks - the problem is, /// that is not stable. If a new fork appears after the fact, we would start ordering the same /// candidate differently, which would result in the same candidate getting queued twice. - relay_parent_block_number: BlockNumber, - /// By adding the `CandidateHash`, we can guarantee a unique ordering across candidates. + relay_parent_block_number: Option, + /// By adding the `CandidateHash`, we can guarantee a unique ordering across candidates with the + /// same relay parent block number. Candidates without `relay_parent_block_number` are ordered by + /// the `candidate_hash` (and treated with the lowest priority, as already mentioned). candidate_hash: CandidateHash, } @@ -287,33 +259,35 @@ impl CandidateComparator { /// /// Useful for testing. #[cfg(test)] - pub fn new_dummy(block_number: BlockNumber, candidate_hash: CandidateHash) -> Self { + pub fn new_dummy(block_number: Option, candidate_hash: CandidateHash) -> Self { Self { relay_parent_block_number: block_number, candidate_hash } } /// Create a candidate comparator for a given candidate. /// /// Returns: - /// `Ok(None)` in case we could not lookup the candidate's relay parent, returns a - /// `FatalError` in case the chain API call fails with an unexpected error. + /// - `Ok(CandidateComparator{Some(relay_parent_block_number), candidate_hash})` when the + /// relay parent can be obtained. This is the happy case. + /// - `Ok(CandidateComparator{None, candidate_hash})` in case the candidate's relay parent + /// can't be obtained. + /// - `FatalError` in case the chain API call fails with an unexpected error. pub async fn new( sender: &mut impl overseer::DisputeCoordinatorSenderTrait, candidate: &CandidateReceipt, - ) -> FatalResult> { + ) -> FatalResult { let candidate_hash = candidate.hash(); - let n = match get_block_number(sender, candidate.descriptor().relay_parent).await? { - None => { - gum::warn!( - target: LOG_TARGET, - candidate_hash = ?candidate_hash, - "Candidate's relay_parent could not be found via chain API - `CandidateComparator could not be provided!" - ); - return Ok(None) - }, - Some(n) => n, - }; + let n = get_block_number(sender, candidate.descriptor().relay_parent).await?; + + if n.is_none() { + gum::warn!( + target: LOG_TARGET, + candidate_hash = ?candidate_hash, + "Candidate's relay_parent could not be found via chain API - `CandidateComparator` \ + with an empty relay parent block number will be provided!" + ); + } - Ok(Some(CandidateComparator { relay_parent_block_number: n, candidate_hash })) + Ok(CandidateComparator { relay_parent_block_number: n, candidate_hash }) } } @@ -333,11 +307,28 @@ impl PartialOrd for CandidateComparator { impl Ord for CandidateComparator { fn cmp(&self, other: &Self) -> Ordering { - match self.relay_parent_block_number.cmp(&other.relay_parent_block_number) { - Ordering::Equal => (), - o => return o, + return match (self.relay_parent_block_number, other.relay_parent_block_number) { + (None, None) => { + // No relay parents for both -> compare hashes + self.candidate_hash.cmp(&other.candidate_hash) + }, + (Some(self_relay_parent_block_num), Some(other_relay_parent_block_num)) => { + match self_relay_parent_block_num.cmp(&other_relay_parent_block_num) { + // if the relay parent is the same for both -> compare hashes + Ordering::Equal => self.candidate_hash.cmp(&other.candidate_hash), + // if not - return the result from comparing the relay parent block numbers + o => return o, + } + }, + (Some(_), None) => { + // Candidates with known relay parents are always with priority + Ordering::Less + }, + (None, Some(_)) => { + // Ditto + Ordering::Greater + }, } - self.candidate_hash.cmp(&other.candidate_hash) } } diff --git a/node/core/dispute-coordinator/src/participation/queues/tests.rs b/node/core/dispute-coordinator/src/participation/queues/tests.rs index 4e9019ebb499..b6af4bd2b55a 100644 --- a/node/core/dispute-coordinator/src/participation/queues/tests.rs +++ b/node/core/dispute-coordinator/src/participation/queues/tests.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +use crate::ParticipationPriority; use ::test_helpers::{dummy_candidate_receipt, dummy_hash}; use assert_matches::assert_matches; use polkadot_primitives::v2::{BlockNumber, Hash}; @@ -31,15 +32,16 @@ fn make_participation_request(hash: Hash) -> ParticipationRequest { /// Make dummy comparator for request, based on the given block number. fn make_dummy_comparator( req: &ParticipationRequest, - relay_parent: BlockNumber, + relay_parent: Option, ) -> CandidateComparator { CandidateComparator::new_dummy(relay_parent, *req.candidate_hash()) } /// Check that dequeuing acknowledges order. /// -/// Any priority item will be dequeued before any best effort items, priority items will be -/// processed in order. Best effort items, based on how often they have been added. +/// Any priority item will be dequeued before any best effort items, priority and best effort with +/// known parent block number items will be processed in order. Best effort items without known parent +/// block number should be treated with lowest priority. #[test] fn ordering_works_as_expected() { let mut queue = Queues::new(); @@ -47,36 +49,69 @@ fn ordering_works_as_expected() { let req_prio = make_participation_request(Hash::repeat_byte(0x02)); let req3 = make_participation_request(Hash::repeat_byte(0x03)); let req_prio_2 = make_participation_request(Hash::repeat_byte(0x04)); - let req5 = make_participation_request(Hash::repeat_byte(0x05)); + let req5_unknown_parent = make_participation_request(Hash::repeat_byte(0x05)); let req_full = make_participation_request(Hash::repeat_byte(0x06)); let req_prio_full = make_participation_request(Hash::repeat_byte(0x07)); - queue.queue_with_comparator(None, req1.clone()).unwrap(); queue - .queue_with_comparator(Some(make_dummy_comparator(&req_prio, 1)), req_prio.clone()) + .queue_with_comparator( + make_dummy_comparator(&req1, Some(1)), + ParticipationPriority::BestEffort, + req1.clone(), + ) + .unwrap(); + queue + .queue_with_comparator( + make_dummy_comparator(&req_prio, Some(1)), + ParticipationPriority::Priority, + req_prio.clone(), + ) .unwrap(); - queue.queue_with_comparator(None, req3.clone()).unwrap(); queue - .queue_with_comparator(Some(make_dummy_comparator(&req_prio_2, 2)), req_prio_2.clone()) + .queue_with_comparator( + make_dummy_comparator(&req3, Some(2)), + ParticipationPriority::BestEffort, + req3.clone(), + ) + .unwrap(); + queue + .queue_with_comparator( + make_dummy_comparator(&req_prio_2, Some(2)), + ParticipationPriority::Priority, + req_prio_2.clone(), + ) + .unwrap(); + queue + .queue_with_comparator( + make_dummy_comparator(&req5_unknown_parent, None), + ParticipationPriority::BestEffort, + req5_unknown_parent.clone(), + ) .unwrap(); - queue.queue_with_comparator(None, req3.clone()).unwrap(); - queue.queue_with_comparator(None, req5.clone()).unwrap(); assert_matches!( - queue.queue_with_comparator(Some(make_dummy_comparator(&req_prio_full, 3)), req_prio_full), + queue.queue_with_comparator( + make_dummy_comparator(&req_prio_full, Some(3)), + ParticipationPriority::Priority, + req_prio_full + ), Err(QueueError::PriorityFull) ); - assert_matches!(queue.queue_with_comparator(None, req_full), Err(QueueError::BestEffortFull)); + assert_matches!( + queue.queue_with_comparator( + make_dummy_comparator(&req_full, Some(3)), + ParticipationPriority::BestEffort, + req_full + ), + Err(QueueError::BestEffortFull) + ); + // Prioritized queue is ordered correctly assert_eq!(queue.dequeue(), Some(req_prio)); assert_eq!(queue.dequeue(), Some(req_prio_2)); + // So is the best-effort + assert_eq!(queue.dequeue(), Some(req1)); assert_eq!(queue.dequeue(), Some(req3)); - assert_matches!( - queue.dequeue(), - Some(r) => { assert!(r == req1 || r == req5) } - ); - assert_matches!( - queue.dequeue(), - Some(r) => { assert!(r == req1 || r == req5) } - ); + assert_eq!(queue.dequeue(), Some(req5_unknown_parent)); + assert_matches!(queue.dequeue(), None); } @@ -89,23 +124,50 @@ fn candidate_is_only_dequeued_once() { let req_best_effort_then_prio = make_participation_request(Hash::repeat_byte(0x03)); let req_prio_then_best_effort = make_participation_request(Hash::repeat_byte(0x04)); - queue.queue_with_comparator(None, req1.clone()).unwrap(); queue - .queue_with_comparator(Some(make_dummy_comparator(&req_prio, 1)), req_prio.clone()) + .queue_with_comparator( + make_dummy_comparator(&req1, None), + ParticipationPriority::BestEffort, + req1.clone(), + ) + .unwrap(); + queue + .queue_with_comparator( + make_dummy_comparator(&req_prio, Some(1)), + ParticipationPriority::Priority, + req_prio.clone(), + ) .unwrap(); // Insert same best effort again: - queue.queue_with_comparator(None, req1.clone()).unwrap(); + queue + .queue_with_comparator( + make_dummy_comparator(&req1, None), + ParticipationPriority::BestEffort, + req1.clone(), + ) + .unwrap(); // insert same prio again: queue - .queue_with_comparator(Some(make_dummy_comparator(&req_prio, 1)), req_prio.clone()) + .queue_with_comparator( + make_dummy_comparator(&req_prio, Some(1)), + ParticipationPriority::Priority, + req_prio.clone(), + ) .unwrap(); // Insert first as best effort: - queue.queue_with_comparator(None, req_best_effort_then_prio.clone()).unwrap(); + queue + .queue_with_comparator( + make_dummy_comparator(&req_best_effort_then_prio, Some(2)), + ParticipationPriority::BestEffort, + req_best_effort_then_prio.clone(), + ) + .unwrap(); // Then as prio: queue .queue_with_comparator( - Some(make_dummy_comparator(&req_best_effort_then_prio, 2)), + make_dummy_comparator(&req_best_effort_then_prio, Some(2)), + ParticipationPriority::Priority, req_best_effort_then_prio.clone(), ) .unwrap(); @@ -116,12 +178,19 @@ fn candidate_is_only_dequeued_once() { // Insert first as prio: queue .queue_with_comparator( - Some(make_dummy_comparator(&req_prio_then_best_effort, 3)), + make_dummy_comparator(&req_prio_then_best_effort, Some(3)), + ParticipationPriority::Priority, req_prio_then_best_effort.clone(), ) .unwrap(); // Then as best effort: - queue.queue_with_comparator(None, req_prio_then_best_effort.clone()).unwrap(); + queue + .queue_with_comparator( + make_dummy_comparator(&req_prio_then_best_effort, Some(3)), + ParticipationPriority::BestEffort, + req_prio_then_best_effort.clone(), + ) + .unwrap(); assert_eq!(queue.dequeue(), Some(req_best_effort_then_prio)); assert_eq!(queue.dequeue(), Some(req_prio_then_best_effort)); diff --git a/node/core/dispute-coordinator/src/participation/tests.rs b/node/core/dispute-coordinator/src/participation/tests.rs index 03772b1918dc..bf149a87286f 100644 --- a/node/core/dispute-coordinator/src/participation/tests.rs +++ b/node/core/dispute-coordinator/src/participation/tests.rs @@ -29,7 +29,10 @@ use parity_scale_codec::Encode; use polkadot_node_primitives::{AvailableData, BlockData, InvalidCandidate, PoV}; use polkadot_node_subsystem::{ jaeger, - messages::{AllMessages, DisputeCoordinatorMessage, RuntimeApiMessage, RuntimeApiRequest}, + messages::{ + AllMessages, ChainApiMessage, DisputeCoordinatorMessage, RuntimeApiMessage, + RuntimeApiRequest, + }, ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, SpawnGlue, }; use polkadot_node_subsystem_test_helpers::{ @@ -221,9 +224,9 @@ fn same_req_wont_get_queued_if_participation_is_already_running() { #[test] fn reqs_get_queued_when_out_of_capacity() { - futures::executor::block_on(async { - let (mut ctx, mut ctx_handle) = make_our_subsystem_context(TaskExecutor::new()); + let (mut ctx, mut ctx_handle) = make_our_subsystem_context(TaskExecutor::new()); + let test = async { let (sender, mut worker_receiver) = mpsc::channel(1); let mut participation = Participation::new(sender); activate_leaf(&mut ctx, &mut participation, 10).await.unwrap(); @@ -239,43 +242,81 @@ fn reqs_get_queued_when_out_of_capacity() { } for _ in 0..MAX_PARALLEL_PARTICIPATIONS + 1 { - assert_matches!( - ctx_handle.recv().await, - AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, tx) - ) => { - tx.send(Err(RecoveryError::Unavailable)).unwrap(); - }, - "overseer did not receive recover available data message", - ); - let result = participation .get_participation_result(&mut ctx, worker_receiver.next().await.unwrap()) .await .unwrap(); - assert_matches!( result.outcome, ParticipationOutcome::Unavailable => {} ); } + // we should not have any further recovery requests: + assert_matches!(worker_receiver.next().timeout(Duration::from_millis(10)).await, None); + }; + + let request_handler = async { + let mut recover_available_data_msg_count = 0; + let mut block_number_msg_count = 0; + + while recover_available_data_msg_count < MAX_PARALLEL_PARTICIPATIONS + 1 || + block_number_msg_count < 1 + { + match ctx_handle.recv().await { + AllMessages::AvailabilityRecovery( + AvailabilityRecoveryMessage::RecoverAvailableData(_, _, _, tx), + ) => { + tx.send(Err(RecoveryError::Unavailable)).unwrap(); + recover_available_data_msg_count += 1; + }, + AllMessages::ChainApi(ChainApiMessage::BlockNumber(_, tx)) => { + tx.send(Ok(None)).unwrap(); + block_number_msg_count += 1; + }, + _ => assert!(false, "Received unexpected message"), + } + } - // we should not have any further results nor recovery requests: + // we should not have any further results assert_matches!(ctx_handle.recv().timeout(Duration::from_millis(10)).await, None); - assert_matches!(worker_receiver.next().timeout(Duration::from_millis(10)).await, None); - }) + }; + + futures::executor::block_on(async { + futures::join!(test, request_handler); + }); } #[test] fn reqs_get_queued_on_no_recent_block() { - futures::executor::block_on(async { - let (mut ctx, mut ctx_handle) = make_our_subsystem_context(TaskExecutor::new()); - + let (mut ctx, mut ctx_handle) = make_our_subsystem_context(TaskExecutor::new()); + let (mut unblock_test, mut wait_for_verification) = mpsc::channel(0); + let test = async { let (sender, _worker_receiver) = mpsc::channel(1); let mut participation = Participation::new(sender); participate(&mut ctx, &mut participation).await.unwrap(); - assert!(ctx_handle.recv().timeout(Duration::from_millis(10)).await.is_none()); + + // We have initiated participation but we'll block `active_leaf` so that we can check that + // the participation is queued in race-free way + let _ = wait_for_verification.next().await.unwrap(); + activate_leaf(&mut ctx, &mut participation, 10).await.unwrap(); + }; + + // Responds to messages from the test and verifies its behaviour + let request_handler = async { + // If we receive `BlockNumber` request this implicitly proves that the participation is queued + assert_matches!( + ctx_handle.recv().await, + AllMessages::ChainApi(ChainApiMessage::BlockNumber(_, tx)) => { + tx.send(Ok(None)).unwrap(); + }, + "overseer did not receive `ChainApiMessage::BlockNumber` message", + ); + + assert!(ctx_handle.recv().timeout(Duration::from_millis(10)).await.is_none()); + + // No activity so the participation is queued => unblock the test + unblock_test.send(()).await.unwrap(); // after activating at least one leaf the recent block // state should be available which should lead to trying @@ -288,7 +329,11 @@ fn reqs_get_queued_on_no_recent_block() { )), "overseer did not receive recover available data message", ); - }) + }; + + futures::executor::block_on(async { + futures::join!(test, request_handler); + }); } #[test] diff --git a/node/core/dispute-coordinator/src/scraping/candidates.rs b/node/core/dispute-coordinator/src/scraping/candidates.rs new file mode 100644 index 000000000000..2fe797768cc2 --- /dev/null +++ b/node/core/dispute-coordinator/src/scraping/candidates.rs @@ -0,0 +1,148 @@ +use polkadot_primitives::v2::{BlockNumber, CandidateHash}; +use std::collections::{BTreeMap, HashMap, HashSet}; + +/// Keeps `CandidateHash` in reference counted way. +/// Each `insert` saves a value with `reference count == 1` or increases the reference +/// count if the value already exists. +/// Each `remove` decreases the reference count for the corresponding `CandidateHash`. +/// If the reference count reaches 0 - the value is removed. +struct RefCountedCandidates { + candidates: HashMap, +} + +impl RefCountedCandidates { + pub fn new() -> Self { + Self { candidates: HashMap::new() } + } + // If `CandidateHash` doesn't exist in the `HashMap` it is created and its reference + // count is set to 1. + // If `CandidateHash` already exists in the `HashMap` its reference count is increased. + pub fn insert(&mut self, candidate: CandidateHash) { + *self.candidates.entry(candidate).or_default() += 1; + } + + // If a `CandidateHash` with reference count equals to 1 is about to be removed - the + // candidate is dropped from the container too. + // If a `CandidateHash` with reference count biger than 1 is about to be removed - the + // reference count is decreased and the candidate remains in the container. + pub fn remove(&mut self, candidate: &CandidateHash) { + match self.candidates.get_mut(candidate) { + Some(v) if *v > 1 => *v -= 1, + Some(v) => { + assert!(*v == 1); + self.candidates.remove(candidate); + }, + None => {}, + } + } + + pub fn contains(&self, candidate: &CandidateHash) -> bool { + self.candidates.contains_key(&candidate) + } +} + +#[cfg(test)] +mod ref_counted_candidates_tests { + use super::*; + use polkadot_primitives::v2::{BlakeTwo256, HashT}; + + #[test] + fn element_is_removed_when_refcount_reaches_zero() { + let mut container = RefCountedCandidates::new(); + + let zero = CandidateHash(BlakeTwo256::hash(&vec![0])); + let one = CandidateHash(BlakeTwo256::hash(&vec![1])); + // add two separate candidates + container.insert(zero); // refcount == 1 + container.insert(one); + + // and increase the reference count for the first + container.insert(zero); // refcount == 2 + + assert!(container.contains(&zero)); + assert!(container.contains(&one)); + + // remove once -> refcount == 1 + container.remove(&zero); + assert!(container.contains(&zero)); + assert!(container.contains(&one)); + + // remove once -> refcount == 0 + container.remove(&zero); + assert!(!container.contains(&zero)); + assert!(container.contains(&one)); + + // remove the other element + container.remove(&one); + assert!(!container.contains(&zero)); + assert!(!container.contains(&one)); + } +} + +/// Keeps track of scraped candidates. Supports `insert`, `remove_up_to_height` and `contains` +/// operations. +pub struct ScrapedCandidates { + /// Main data structure which keeps the candidates we know about. `contains` does lookups only here. + candidates: RefCountedCandidates, + /// Keeps track at which block number a candidate was inserted. Used in `remove_up_to_height`. + /// Without this tracking we won't be able to remove all candidates before block X. + candidates_by_block_number: BTreeMap>, +} + +impl ScrapedCandidates { + pub fn new() -> Self { + Self { + candidates: RefCountedCandidates::new(), + candidates_by_block_number: BTreeMap::new(), + } + } + + pub fn contains(&self, candidate_hash: &CandidateHash) -> bool { + self.candidates.contains(candidate_hash) + } + + // Removes all candidates up to a given height. The candidates at the block height are NOT removed. + pub fn remove_up_to_height(&mut self, height: &BlockNumber) { + let not_stale = self.candidates_by_block_number.split_off(&height); + let stale = std::mem::take(&mut self.candidates_by_block_number); + self.candidates_by_block_number = not_stale; + for candidates in stale.values() { + for c in candidates { + self.candidates.remove(c); + } + } + } + + pub fn insert(&mut self, block_number: BlockNumber, candidate_hash: CandidateHash) { + self.candidates.insert(candidate_hash); + self.candidates_by_block_number + .entry(block_number) + .or_default() + .insert(candidate_hash); + } + + // Used only for tests to verify the pruning doesn't leak data. + #[cfg(test)] + pub fn candidates_by_block_number_is_empty(&self) -> bool { + self.candidates_by_block_number.is_empty() + } +} + +#[cfg(test)] +mod scraped_candidates_tests { + use super::*; + use polkadot_primitives::v2::{BlakeTwo256, HashT}; + + #[test] + fn stale_candidates_are_removed() { + let mut candidates = ScrapedCandidates::new(); + let target = CandidateHash(BlakeTwo256::hash(&vec![1, 2, 3])); + candidates.insert(1, target); + + assert!(candidates.contains(&target)); + + candidates.remove_up_to_height(&2); + assert!(!candidates.contains(&target)); + assert!(candidates.candidates_by_block_number_is_empty()); + } +} diff --git a/node/core/dispute-coordinator/src/scraping/mod.rs b/node/core/dispute-coordinator/src/scraping/mod.rs index 7d5d33e1ff4b..7f4f819756e3 100644 --- a/node/core/dispute-coordinator/src/scraping/mod.rs +++ b/node/core/dispute-coordinator/src/scraping/mod.rs @@ -14,15 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use std::{ - collections::{BTreeMap, HashSet}, - num::NonZeroUsize, -}; +use std::num::NonZeroUsize; use futures::channel::oneshot; use lru::LruCache; -use polkadot_node_primitives::MAX_FINALITY_LAG; +use polkadot_node_primitives::{DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION, MAX_FINALITY_LAG}; use polkadot_node_subsystem::{ messages::ChainApiMessage, overseer, ActivatedLeaf, ActiveLeavesUpdate, ChainApiError, SubsystemSender, @@ -40,6 +37,8 @@ use crate::{ #[cfg(test)] mod tests; +mod candidates; + /// Number of hashes to keep in the LRU. /// /// @@ -58,18 +57,21 @@ const LRU_OBSERVED_BLOCKS_CAPACITY: NonZeroUsize = match NonZeroUsize::new(20) { /// /// Concretely: /// -/// - Monitors for inclusion events to keep track of candidates that have been included on chains. +/// - Monitors for `CandidateIncluded` events to keep track of candidates that have been +/// included on chains. +/// - Monitors for `CandidateBacked` events to keep track of all backed candidates. /// - Calls `FetchOnChainVotes` for each block to gather potentially missed votes from chain. /// /// With this information it provides a `CandidateComparator` and as a return value of /// `process_active_leaves_update` any scraped votes. +/// +/// Scraped candidates are available `DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION` more blocks +/// after finalization as a precaution not to prune them prematurely. pub struct ChainScraper { /// All candidates we have seen included, which not yet have been finalized. - included_candidates: HashSet, - /// including block -> `CandidateHash` - /// - /// We need this to clean up `included_candidates` on finalization. - candidates_by_block_number: BTreeMap>, + included_candidates: candidates::ScrapedCandidates, + /// All candidates we have seen backed + backed_candidates: candidates::ScrapedCandidates, /// Latest relay blocks observed by the provider. /// /// We assume that ancestors of cached blocks are already processed, i.e. we have saved @@ -96,8 +98,8 @@ impl ChainScraper { Sender: overseer::DisputeCoordinatorSenderTrait, { let mut s = Self { - included_candidates: HashSet::new(), - candidates_by_block_number: BTreeMap::new(), + included_candidates: candidates::ScrapedCandidates::new(), + backed_candidates: candidates::ScrapedCandidates::new(), last_observed_blocks: LruCache::new(LRU_OBSERVED_BLOCKS_CAPACITY), }; let update = @@ -107,10 +109,15 @@ impl ChainScraper { } /// Check whether we have seen a candidate included on any chain. - pub fn is_candidate_included(&mut self, candidate_hash: &CandidateHash) -> bool { + pub fn is_candidate_included(&self, candidate_hash: &CandidateHash) -> bool { self.included_candidates.contains(candidate_hash) } + /// Check whether the candidate is backed + pub fn is_candidate_backed(&self, candidate_hash: &CandidateHash) -> bool { + self.backed_candidates.contains(candidate_hash) + } + /// Query active leaves for any candidate `CandidateEvent::CandidateIncluded` events. /// /// and updates current heads, so we can query candidates for all non finalized blocks. @@ -120,7 +127,7 @@ impl ChainScraper { &mut self, sender: &mut Sender, update: &ActiveLeavesUpdate, - ) -> crate::error::Result> + ) -> Result> where Sender: overseer::DisputeCoordinatorSenderTrait, { @@ -158,21 +165,28 @@ impl ChainScraper { /// Prune finalized candidates. /// - /// Once a candidate lives in a relay chain block that's behind the finalized chain/got - /// finalized, we can treat it as low priority. - pub fn process_finalized_block(&mut self, finalized: &BlockNumber) { - let not_finalized = self.candidates_by_block_number.split_off(finalized); - let finalized = std::mem::take(&mut self.candidates_by_block_number); - self.candidates_by_block_number = not_finalized; - // Clean up finalized: - for finalized_candidate in finalized.into_values().flatten() { - self.included_candidates.remove(&finalized_candidate); + /// We keep each candidate for `DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION` blocks after finalization. + /// After that we treat it as low priority. + pub fn process_finalized_block(&mut self, finalized_block_number: &BlockNumber) { + // `DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION - 1` because `finalized_block_number`counts to the + // candidate lifetime. + match finalized_block_number.checked_sub(DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION - 1) + { + Some(key_to_prune) => { + self.backed_candidates.remove_up_to_height(&key_to_prune); + self.included_candidates.remove_up_to_height(&key_to_prune); + }, + None => { + // Nothing to prune. We are still in the beginning of the chain and there are not + // enough finalized blocks yet. + }, } + {} } /// Process candidate events of a block. /// - /// Keep track of all included candidates. + /// Keep track of all included and backed candidates. async fn process_candidate_events( &mut self, sender: &mut Sender, @@ -182,28 +196,33 @@ impl ChainScraper { where Sender: overseer::DisputeCoordinatorSenderTrait, { - // Get included events: - let included = - get_candidate_events(sender, block_hash) - .await? - .into_iter() - .filter_map(|ev| match ev { - CandidateEvent::CandidateIncluded(receipt, _, _, _) => Some(receipt), - _ => None, - }); - for receipt in included { - let candidate_hash = receipt.hash(); - gum::trace!( - target: LOG_TARGET, - ?candidate_hash, - ?block_number, - "Processing included event" - ); - self.included_candidates.insert(candidate_hash); - self.candidates_by_block_number - .entry(block_number) - .or_default() - .insert(candidate_hash); + // Get included and backed events: + for ev in get_candidate_events(sender, block_hash).await? { + match ev { + CandidateEvent::CandidateIncluded(receipt, _, _, _) => { + let candidate_hash = receipt.hash(); + gum::trace!( + target: LOG_TARGET, + ?candidate_hash, + ?block_number, + "Processing included event" + ); + self.included_candidates.insert(block_number, candidate_hash); + }, + CandidateEvent::CandidateBacked(receipt, _, _, _) => { + let candidate_hash = receipt.hash(); + gum::trace!( + target: LOG_TARGET, + ?candidate_hash, + ?block_number, + "Processing backed event" + ); + self.backed_candidates.insert(block_number, candidate_hash); + }, + _ => { + // skip the rest + }, + } } Ok(()) } diff --git a/node/core/dispute-coordinator/src/scraping/tests.rs b/node/core/dispute-coordinator/src/scraping/tests.rs index b6b5a1f633bf..3a6befa2002d 100644 --- a/node/core/dispute-coordinator/src/scraping/tests.rs +++ b/node/core/dispute-coordinator/src/scraping/tests.rs @@ -23,6 +23,7 @@ use parity_scale_codec::Encode; use sp_core::testing::TaskExecutor; use ::test_helpers::{dummy_collator, dummy_collator_signature, dummy_hash}; +use polkadot_node_primitives::DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION; use polkadot_node_subsystem::{ jaeger, messages::{ @@ -73,7 +74,12 @@ impl TestState { assert_finalized_block_number_request(&mut ctx_handle, finalized_block_number).await; gum::trace!(target: LOG_TARGET, "After assert_finalized_block_number"); // No ancestors requests, as list would be empty. - assert_candidate_events_request(&mut ctx_handle, &chain).await; + assert_candidate_events_request( + &mut ctx_handle, + &chain, + get_backed_and_included_candidate_events, + ) + .await; assert_chain_vote_request(&mut ctx_handle, &chain).await; }; @@ -112,6 +118,10 @@ async fn process_active_leaves_update( .unwrap(); } +fn process_finalized_block(scraper: &mut ChainScraper, finalized: &BlockNumber) { + scraper.process_finalized_block(&finalized) +} + fn make_candidate_receipt(relay_parent: Hash) -> CandidateReceipt { let zeros = dummy_hash(); let descriptor = CandidateDescriptor { @@ -145,16 +155,66 @@ fn get_block_number_hash(n: BlockNumber) -> Hash { } /// Get a dummy event that corresponds to candidate inclusion for the given block number. -fn get_candidate_included_events(block_number: BlockNumber) -> Vec { - vec![CandidateEvent::CandidateIncluded( - make_candidate_receipt(get_block_number_hash(block_number)), +fn get_backed_and_included_candidate_events(block_number: BlockNumber) -> Vec { + let candidate_receipt = make_candidate_receipt(get_block_number_hash(block_number)); + vec![ + CandidateEvent::CandidateIncluded( + candidate_receipt.clone(), + HeadData::default(), + CoreIndex::from(0), + GroupIndex::from(0), + ), + CandidateEvent::CandidateBacked( + candidate_receipt, + HeadData::default(), + CoreIndex::from(0), + GroupIndex::from(0), + ), + ] +} + +fn get_backed_candidate_event(block_number: BlockNumber) -> Vec { + let candidate_receipt = make_candidate_receipt(get_block_number_hash(block_number)); + vec![CandidateEvent::CandidateBacked( + candidate_receipt, HeadData::default(), CoreIndex::from(0), GroupIndex::from(0), )] } +/// Hash for a 'magic' candidate. This is meant to be a special candidate used to verify special cases. +fn get_magic_candidate_hash() -> Hash { + BlakeTwo256::hash(&"abc".encode()) +} +/// Get a dummy event that corresponds to candidate inclusion for a hardcoded block number. +/// Used to simulate candidates included multiple times at different block heights. +fn get_backed_and_included_magic_candidate_events( + _block_number: BlockNumber, +) -> Vec { + let candidate_receipt = make_candidate_receipt(get_magic_candidate_hash()); + vec![ + CandidateEvent::CandidateIncluded( + candidate_receipt.clone(), + HeadData::default(), + CoreIndex::from(0), + GroupIndex::from(0), + ), + CandidateEvent::CandidateBacked( + candidate_receipt, + HeadData::default(), + CoreIndex::from(0), + GroupIndex::from(0), + ), + ] +} -async fn assert_candidate_events_request(virtual_overseer: &mut VirtualOverseer, chain: &[Hash]) { +async fn assert_candidate_events_request( + virtual_overseer: &mut VirtualOverseer, + chain: &[Hash], + event_generator: F, +) where + F: Fn(u32) -> Vec, +{ assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::RuntimeApi(RuntimeApiMessage::Request( @@ -163,7 +223,7 @@ async fn assert_candidate_events_request(virtual_overseer: &mut VirtualOverseer, )) => { let maybe_block_number = chain.iter().position(|h| *h == hash); let response = maybe_block_number - .map(|num| get_candidate_included_events(num as u32)) + .map(|num| event_generator(num as u32)) .unwrap_or_default(); tx.send(Ok(response)).unwrap(); } @@ -207,12 +267,15 @@ async fn assert_block_ancestors_request(virtual_overseer: &mut VirtualOverseer, ); } -async fn overseer_process_active_leaves_update( +async fn overseer_process_active_leaves_update( virtual_overseer: &mut VirtualOverseer, chain: &[Hash], finalized_block: BlockNumber, expected_ancestry_len: usize, -) { + event_generator: F, +) where + F: Fn(u32) -> Vec + Clone, +{ // Before walking through ancestors provider requests latest finalized block number. assert_finalized_block_number_request(virtual_overseer, finalized_block).await; // Expect block ancestors requests with respect to the ancestry step. @@ -221,7 +284,7 @@ async fn overseer_process_active_leaves_update( } // For each ancestry and the head return corresponding candidates inclusions. for _ in 0..expected_ancestry_len { - assert_candidate_events_request(virtual_overseer, chain).await; + assert_candidate_events_request(virtual_overseer, chain, event_generator.clone()).await; assert_chain_vote_request(virtual_overseer, chain).await; } } @@ -236,7 +299,9 @@ fn scraper_provides_included_state_when_initialized() { let TestState { mut chain, mut scraper, mut ctx } = state; assert!(!scraper.is_candidate_included(&candidate_2.hash())); + assert!(!scraper.is_candidate_backed(&candidate_2.hash())); assert!(scraper.is_candidate_included(&candidate_1.hash())); + assert!(scraper.is_candidate_backed(&candidate_1.hash())); // After next active leaves update we should see the candidate included. let next_update = next_leaf(&mut chain); @@ -248,11 +313,13 @@ fn scraper_provides_included_state_when_initialized() { &chain, finalized_block_number, expected_ancestry_len, + get_backed_and_included_candidate_events, ); join(process_active_leaves_update(ctx.sender(), &mut scraper, next_update), overseer_fut) .await; assert!(scraper.is_candidate_included(&candidate_2.hash())); + assert!(scraper.is_candidate_backed(&candidate_2.hash())); }); } @@ -274,6 +341,7 @@ fn scraper_requests_candidates_of_leaf_ancestors() { &chain, finalized_block_number, BLOCKS_TO_SKIP, + get_backed_and_included_candidate_events, ); join(process_active_leaves_update(ctx.sender(), &mut scraper, next_update), overseer_fut) .await; @@ -282,6 +350,7 @@ fn scraper_requests_candidates_of_leaf_ancestors() { for block_number in 1..next_block_number { let candidate = make_candidate_receipt(get_block_number_hash(block_number)); assert!(scraper.is_candidate_included(&candidate.hash())); + assert!(scraper.is_candidate_backed(&candidate.hash())); } }); } @@ -304,6 +373,7 @@ fn scraper_requests_candidates_of_non_cached_ancestors() { &chain, finalized_block_number, BLOCKS_TO_SKIP[0], + get_backed_and_included_candidate_events, ); join(process_active_leaves_update(ctx.sender(), &mut ordering, next_update), overseer_fut) .await; @@ -315,6 +385,7 @@ fn scraper_requests_candidates_of_non_cached_ancestors() { &chain, finalized_block_number, BLOCKS_TO_SKIP[1], + get_backed_and_included_candidate_events, ); join(process_active_leaves_update(ctx.sender(), &mut ordering, next_update), overseer_fut) .await; @@ -340,8 +411,170 @@ fn scraper_requests_candidates_of_non_finalized_ancestors() { &chain, finalized_block_number, BLOCKS_TO_SKIP - finalized_block_number as usize, // Expect the provider not to go past finalized block. + get_backed_and_included_candidate_events, ); join(process_active_leaves_update(ctx.sender(), &mut ordering, next_update), overseer_fut) .await; }); } + +#[test] +fn scraper_prunes_finalized_candidates() { + const TEST_TARGET_BLOCK_NUMBER: BlockNumber = 2; + + // How many blocks should we skip before sending a leaf update. + const BLOCKS_TO_SKIP: usize = 3; + + futures::executor::block_on(async { + let (state, mut virtual_overseer) = TestState::new().await; + + let TestState { mut chain, mut scraper, mut ctx } = state; + + // 1 because `TestState` starts at leaf 1. + let next_update = (1..BLOCKS_TO_SKIP).map(|_| next_leaf(&mut chain)).last().unwrap(); + + let mut finalized_block_number = 1; + let expected_ancestry_len = BLOCKS_TO_SKIP - finalized_block_number as usize; + let overseer_fut = overseer_process_active_leaves_update( + &mut virtual_overseer, + &chain, + finalized_block_number, + expected_ancestry_len, + |block_num| { + if block_num == TEST_TARGET_BLOCK_NUMBER { + get_backed_and_included_candidate_events(block_num) + } else { + vec![] + } + }, + ); + join(process_active_leaves_update(ctx.sender(), &mut scraper, next_update), overseer_fut) + .await; + + let candidate = make_candidate_receipt(get_block_number_hash(TEST_TARGET_BLOCK_NUMBER)); + + // After `DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION` blocks the candidate should be removed + finalized_block_number = + TEST_TARGET_BLOCK_NUMBER + DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION; + process_finalized_block(&mut scraper, &finalized_block_number); + + assert!(!scraper.is_candidate_backed(&candidate.hash())); + assert!(!scraper.is_candidate_included(&candidate.hash())); + }); +} + +#[test] +fn scraper_handles_backed_but_not_included_candidate() { + const TEST_TARGET_BLOCK_NUMBER: BlockNumber = 2; + + // How many blocks should we skip before sending a leaf update. + const BLOCKS_TO_SKIP: usize = 3; + + futures::executor::block_on(async { + let (state, mut virtual_overseer) = TestState::new().await; + + let TestState { mut chain, mut scraper, mut ctx } = state; + + let next_update = (1..BLOCKS_TO_SKIP as BlockNumber) + .map(|_| next_leaf(&mut chain)) + .last() + .unwrap(); + + // Add `ActiveLeavesUpdate` containing `CandidateBacked` event for block `BLOCK_WITH_EVENTS` + let mut finalized_block_number = 1; + let expected_ancestry_len = BLOCKS_TO_SKIP - finalized_block_number as usize; + let overseer_fut = overseer_process_active_leaves_update( + &mut virtual_overseer, + &chain, + finalized_block_number, + expected_ancestry_len, + |block_num| { + if block_num == TEST_TARGET_BLOCK_NUMBER { + get_backed_candidate_event(block_num) + } else { + vec![] + } + }, + ); + join(process_active_leaves_update(ctx.sender(), &mut scraper, next_update), overseer_fut) + .await; + + // Finalize blocks to enforce pruning of scraped events + finalized_block_number += 1; + process_finalized_block(&mut scraper, &finalized_block_number); + + // `FIRST_TEST_BLOCK` is finalized, which is within `BACKED_CANDIDATE_LIFETIME_AFTER_FINALIZATION` window. + // The candidate should still be backed. + let candidate = make_candidate_receipt(get_block_number_hash(TEST_TARGET_BLOCK_NUMBER)); + assert!(!scraper.is_candidate_included(&candidate.hash())); + assert!(scraper.is_candidate_backed(&candidate.hash())); + + // Bump the finalized block outside `BACKED_CANDIDATE_LIFETIME_AFTER_FINALIZATION`. + // The candidate should be removed. + assert!( + finalized_block_number < + TEST_TARGET_BLOCK_NUMBER + DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION + ); + finalized_block_number += + TEST_TARGET_BLOCK_NUMBER + DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION; + process_finalized_block(&mut scraper, &finalized_block_number); + + assert!(!scraper.is_candidate_included(&candidate.hash())); + assert!(!scraper.is_candidate_backed(&candidate.hash())); + }); +} + +#[test] +fn scraper_handles_the_same_candidate_incuded_in_two_different_block_heights() { + // Same candidate will be inclued in these two leaves + let test_targets = vec![2, 3]; + + // How many blocks should we skip before sending a leaf update. + const BLOCKS_TO_SKIP: usize = 3; + + futures::executor::block_on(async { + let (state, mut virtual_overseer) = TestState::new().await; + + let TestState { mut chain, mut scraper, mut ctx } = state; + + // 1 because `TestState` starts at leaf 1. + let next_update = (1..BLOCKS_TO_SKIP).map(|_| next_leaf(&mut chain)).last().unwrap(); + + // Now we will add the same magic candidate at two different block heights. + // Check `get_backed_and_included_magic_candidate_event` implementation + let mut finalized_block_number = 1; + let expected_ancestry_len = BLOCKS_TO_SKIP - finalized_block_number as usize; + let overseer_fut = overseer_process_active_leaves_update( + &mut virtual_overseer, + &chain, + finalized_block_number, + expected_ancestry_len, + |block_num| { + if test_targets.contains(&block_num) { + get_backed_and_included_magic_candidate_events(block_num) + } else { + vec![] + } + }, + ); + join(process_active_leaves_update(ctx.sender(), &mut scraper, next_update), overseer_fut) + .await; + + // Finalize blocks to enforce pruning of scraped events. + // The magic candidate was added twice, so it shouldn't be removed if we finalize two more blocks. + finalized_block_number = test_targets.first().expect("there are two block nums") + + DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION; + process_finalized_block(&mut scraper, &finalized_block_number); + + let magic_candidate = make_candidate_receipt(get_magic_candidate_hash()); + assert!(scraper.is_candidate_backed(&magic_candidate.hash())); + assert!(scraper.is_candidate_included(&magic_candidate.hash())); + + // On the next finalization the magic candidate should be removed + finalized_block_number += 1; + process_finalized_block(&mut scraper, &finalized_block_number); + + assert!(!scraper.is_candidate_backed(&magic_candidate.hash())); + assert!(!scraper.is_candidate_included(&magic_candidate.hash())); + }); +} diff --git a/node/core/dispute-coordinator/src/tests.rs b/node/core/dispute-coordinator/src/tests.rs index aaef00999259..75d37790c3d7 100644 --- a/node/core/dispute-coordinator/src/tests.rs +++ b/node/core/dispute-coordinator/src/tests.rs @@ -31,7 +31,9 @@ use futures::{ use polkadot_node_subsystem_util::database::Database; -use polkadot_node_primitives::{SignedDisputeStatement, SignedFullStatement, Statement}; +use polkadot_node_primitives::{ + DisputeStatus, SignedDisputeStatement, SignedFullStatement, Statement, +}; use polkadot_node_subsystem::{ messages::{ ApprovalVotingMessage, ChainApiMessage, DisputeCoordinatorMessage, @@ -55,12 +57,14 @@ use polkadot_node_subsystem::{ messages::{AllMessages, BlockDescription, RuntimeApiMessage, RuntimeApiRequest}, ActivatedLeaf, ActiveLeavesUpdate, LeafStatus, }; -use polkadot_node_subsystem_test_helpers::{make_subsystem_context, TestSubsystemContextHandle}; +use polkadot_node_subsystem_test_helpers::{ + make_buffered_subsystem_context, TestSubsystemContextHandle, +}; use polkadot_primitives::v2::{ - ApprovalVote, BlockNumber, CandidateCommitments, CandidateHash, CandidateReceipt, - DisputeStatement, Hash, Header, MultiDisputeStatementSet, ScrapedOnChainVotes, SessionIndex, - SessionInfo, SigningContext, ValidDisputeStatementKind, ValidatorId, ValidatorIndex, - ValidatorSignature, + ApprovalVote, BlockNumber, CandidateCommitments, CandidateEvent, CandidateHash, + CandidateReceipt, CoreIndex, DisputeStatement, GroupIndex, Hash, HeadData, Header, IndexedVec, + MultiDisputeStatementSet, ScrapedOnChainVotes, SessionIndex, SessionInfo, SigningContext, + ValidDisputeStatementKind, ValidatorId, ValidatorIndex, ValidatorSignature, }; use crate::{ @@ -100,6 +104,38 @@ async fn overseer_recv(virtual_overseer: &mut VirtualOverseer) -> AllMessages { .expect("overseer `recv` timed out") } +enum VoteType { + Backing, + Explicit, +} + +/// Helper to condense repeated code that creates vote pairs, one valid and one +/// invalid. Optionally the valid vote of the pair can be made a backing vote. +async fn generate_opposing_votes_pair( + test_state: &TestState, + valid_voter_idx: ValidatorIndex, + invalid_voter_idx: ValidatorIndex, + candidate_hash: CandidateHash, + session: SessionIndex, + valid_vote_type: VoteType, +) -> (SignedDisputeStatement, SignedDisputeStatement) { + let valid_vote = match valid_vote_type { + VoteType::Backing => + test_state + .issue_backing_statement_with_index(valid_voter_idx, candidate_hash, session) + .await, + VoteType::Explicit => + test_state + .issue_explicit_statement_with_index(valid_voter_idx, candidate_hash, session, true) + .await, + }; + let invalid_vote = test_state + .issue_explicit_statement_with_index(invalid_voter_idx, candidate_hash, session, false) + .await; + + (valid_vote, invalid_vote) +} + #[derive(Clone)] struct MockClock { time: Arc, @@ -125,8 +161,8 @@ impl MockClock { struct TestState { validators: Vec, - validator_public: Vec, - validator_groups: Vec>, + validator_public: IndexedVec, + validator_groups: IndexedVec>, master_keystore: Arc, subsystem_keystore: Arc, db: Arc, @@ -163,11 +199,11 @@ impl Default for TestState { .map(|k| ValidatorId::from(k.0.public())) .collect(); - let validator_groups = vec![ + let validator_groups = IndexedVec::>::from(vec![ vec![ValidatorIndex(0), ValidatorIndex(1)], vec![ValidatorIndex(2), ValidatorIndex(3)], vec![ValidatorIndex(4), ValidatorIndex(5), ValidatorIndex(6)], - ]; + ]); let master_keystore = make_keystore(validators.iter().map(|v| v.1.clone())).into(); let subsystem_keystore = @@ -176,7 +212,7 @@ impl Default for TestState { let db = kvdb_memorydb::create(1); let db = polkadot_node_subsystem_util::database::kvdb_impl::DbAdapter::new(db, &[]); let db = Arc::new(db); - let config = Config { col_data: 0 }; + let config = Config { col_dispute_data: 0, col_session_data: 1 }; let genesis_header = Header { parent_hash: Hash::zero(), @@ -212,6 +248,7 @@ impl TestState { virtual_overseer: &mut VirtualOverseer, session: SessionIndex, block_number: BlockNumber, + candidate_events: Vec, ) { assert!(block_number > 0); @@ -239,8 +276,14 @@ impl TestState { ))) .await; - self.handle_sync_queries(virtual_overseer, block_hash, block_number, session) - .await; + self.handle_sync_queries( + virtual_overseer, + block_hash, + block_number, + session, + candidate_events, + ) + .await; } async fn handle_sync_queries( @@ -249,8 +292,10 @@ impl TestState { block_hash: Hash, block_number: BlockNumber, session: SessionIndex, + candidate_events: Vec, ) { // Order of messages is not fixed (different on initializing): + #[derive(Debug)] struct FinishedSteps { got_session_information: bool, got_scraping_information: bool, @@ -268,7 +313,8 @@ impl TestState { let mut finished_steps = FinishedSteps::new(); while !finished_steps.is_done() { - match overseer_recv(virtual_overseer).await { + let recv = overseer_recv(virtual_overseer).await; + match recv { AllMessages::RuntimeApi(RuntimeApiMessage::Request( h, RuntimeApiRequest::SessionIndexForChild(tx), @@ -282,36 +328,38 @@ impl TestState { let _ = tx.send(Ok(session)); // Queries for fetching earliest unfinalized block session. See `RollingSessionWindow`. - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber( - s_tx, - )) => { - let _ = s_tx.send(Ok(block_number)); - } - ); + if self.known_session.is_none() { + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber( + s_tx, + )) => { + let _ = s_tx.send(Ok(block_number)); + } + ); - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::ChainApi(ChainApiMessage::FinalizedBlockHash( - number, - s_tx, - )) => { - assert_eq!(block_number, number); - let _ = s_tx.send(Ok(Some(block_hash))); - } - ); + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockHash( + number, + s_tx, + )) => { + assert_eq!(block_number, number); + let _ = s_tx.send(Ok(Some(block_hash))); + } + ); - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - h, - RuntimeApiRequest::SessionIndexForChild(s_tx), - )) => { - assert_eq!(h, block_hash); - let _ = s_tx.send(Ok(session)); - } - ); + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + h, + RuntimeApiRequest::SessionIndexForChild(s_tx), + )) => { + assert_eq!(h, block_hash); + let _ = s_tx.send(Ok(session)); + } + ); + } // No queries, if subsystem knows about this session already. if self.known_session == Some(session) { @@ -348,7 +396,7 @@ impl TestState { _new_leaf, RuntimeApiRequest::CandidateEvents(tx), )) => { - tx.send(Ok(Vec::new())).unwrap(); + tx.send(Ok(candidate_events.clone())).unwrap(); } ); gum::trace!("After answering runtime api request"); @@ -368,6 +416,10 @@ impl TestState { ); gum::trace!("After answering runtime API request (votes)"); }, + AllMessages::ChainApi(ChainApiMessage::BlockNumber(hash, tx)) => { + let block_num = self.headers.get(&hash).map(|header| header.number); + tx.send(Ok(block_num)).unwrap(); + }, msg => { panic!("Received unexpected message in `handle_sync_queries`: {:?}", msg); }, @@ -397,8 +449,14 @@ impl TestState { ))) .await; - self.handle_sync_queries(virtual_overseer, *leaf, n as BlockNumber, session) - .await; + self.handle_sync_queries( + virtual_overseer, + *leaf, + n as BlockNumber, + session, + Vec::new(), + ) + .await; } } @@ -431,7 +489,7 @@ impl TestState { session: SessionIndex, valid: bool, ) -> SignedDisputeStatement { - let public = self.validator_public[index.0 as usize].clone(); + let public = self.validator_public.get(index).unwrap().clone(); let keystore = self.master_keystore.clone() as SyncCryptoStorePtr; @@ -501,7 +559,7 @@ impl TestState { F: FnOnce(TestState, VirtualOverseer) -> BoxFuture<'static, TestState>, { self.known_session = None; - let (ctx, ctx_handle) = make_subsystem_context(TaskExecutor::new()); + let (ctx, ctx_handle) = make_buffered_subsystem_context(TaskExecutor::new(), 1); let subsystem = DisputeCoordinatorSubsystem::new( self.db.clone(), self.config.clone(), @@ -552,6 +610,26 @@ fn make_invalid_candidate_receipt() -> CandidateReceipt { dummy_candidate_receipt_bad_sig(Default::default(), Some(Default::default())) } +// Generate a `CandidateBacked` event from a `CandidateReceipt`. The rest is dummy data. +fn make_candidate_backed_event(candidate_receipt: CandidateReceipt) -> CandidateEvent { + CandidateEvent::CandidateBacked( + candidate_receipt, + HeadData(Vec::new()), + CoreIndex(0), + GroupIndex(0), + ) +} + +// Generate a `CandidateIncluded` event from a `CandidateReceipt`. The rest is dummy data. +fn make_candidate_included_event(candidate_receipt: CandidateReceipt) -> CandidateEvent { + CandidateEvent::CandidateIncluded( + candidate_receipt, + HeadData(Vec::new()), + CoreIndex(0), + GroupIndex(0), + ) +} + /// Handle request for approval votes: pub async fn handle_approval_vote_request( ctx_handle: &mut VirtualOverseer, @@ -583,33 +661,29 @@ fn too_many_unconfirmed_statements_are_considered_spam() { let candidate_receipt2 = make_invalid_candidate_receipt(); let candidate_hash2 = candidate_receipt2.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let valid_vote1 = test_state - .issue_backing_statement_with_index(ValidatorIndex(3), candidate_hash1, session) - .await; - - let invalid_vote1 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash1, - session, - false, - ) + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) .await; - let valid_vote2 = test_state - .issue_backing_statement_with_index(ValidatorIndex(3), candidate_hash2, session) - .await; + let (valid_vote1, invalid_vote1) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(3), + ValidatorIndex(1), + candidate_hash1, + session, + VoteType::Backing, + ) + .await; - let invalid_vote2 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash2, - session, - false, - ) - .await; + let (valid_vote2, invalid_vote2) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(3), + ValidatorIndex(1), + candidate_hash2, + session, + VoteType::Backing, + ) + .await; gum::trace!("Before sending `ImportStatements`"); virtual_overseer @@ -630,8 +704,9 @@ fn too_many_unconfirmed_statements_are_considered_spam() { handle_approval_vote_request(&mut virtual_overseer, &candidate_hash1, HashMap::new()) .await; - // Participation has to fail, otherwise the dispute will be confirmed. - participation_missing_availability(&mut virtual_overseer).await; + // Participation has to fail here, otherwise the dispute will be confirmed. However + // participation won't happen at all because the dispute is neither backed, not confirmed + // nor the candidate is included. Or in other words - we'll refrain from participation. { let (tx, rx) = oneshot::channel(); @@ -641,7 +716,10 @@ fn too_many_unconfirmed_statements_are_considered_spam() { }) .await; - assert_eq!(rx.await.unwrap(), vec![(session, candidate_hash1)]); + assert_eq!( + rx.await.unwrap(), + vec![(session, candidate_hash1, DisputeStatus::Active)] + ); let (tx, rx) = oneshot::channel(); virtual_overseer @@ -654,7 +732,7 @@ fn too_many_unconfirmed_statements_are_considered_spam() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 1); + assert_eq!(votes.valid.raw().len(), 1); assert_eq!(votes.invalid.len(), 1); } @@ -714,20 +792,19 @@ fn approval_vote_import_works() { let candidate_receipt1 = make_valid_candidate_receipt(); let candidate_hash1 = candidate_receipt1.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let valid_vote1 = test_state - .issue_backing_statement_with_index(ValidatorIndex(3), candidate_hash1, session) + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) .await; - let invalid_vote1 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash1, - session, - false, - ) - .await; + let (valid_vote1, invalid_vote1) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(3), + ValidatorIndex(1), + candidate_hash1, + session, + VoteType::Backing, + ) + .await; let approval_vote = test_state.issue_approval_vote_with_index( ValidatorIndex(4), @@ -754,11 +831,12 @@ fn approval_vote_import_works() { let approval_votes = [(ValidatorIndex(4), approval_vote.into_validator_signature())] .into_iter() .collect(); + handle_approval_vote_request(&mut virtual_overseer, &candidate_hash1, approval_votes) .await; - // Participation has to fail, otherwise the dispute will be confirmed. - participation_missing_availability(&mut virtual_overseer).await; + // Participation won't happen here because the dispute is neither backed, not confirmed + // nor the candidate is included. Or in other words - we'll refrain from participation. { let (tx, rx) = oneshot::channel(); @@ -768,7 +846,10 @@ fn approval_vote_import_works() { }) .await; - assert_eq!(rx.await.unwrap(), vec![(session, candidate_hash1)]); + assert_eq!( + rx.await.unwrap(), + vec![(session, candidate_hash1, DisputeStatus::Active)] + ); let (tx, rx) = oneshot::channel(); virtual_overseer @@ -781,8 +862,11 @@ fn approval_vote_import_works() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 2); - assert!(votes.valid.get(&ValidatorIndex(4)).is_some(), "Approval vote is missing!"); + assert_eq!(votes.valid.raw().len(), 2); + assert!( + votes.valid.raw().get(&ValidatorIndex(4)).is_some(), + "Approval vote is missing!" + ); assert_eq!(votes.invalid.len(), 1); } @@ -809,43 +893,37 @@ fn dispute_gets_confirmed_via_participation() { let candidate_receipt2 = make_invalid_candidate_receipt(); let candidate_hash2 = candidate_receipt2.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let valid_vote1 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(3), - candidate_hash1, - session, - true, - ) - .await; - - let invalid_vote1 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash1, + test_state + .activate_leaf_at_session( + &mut virtual_overseer, session, - false, + 1, + vec![ + make_candidate_backed_event(candidate_receipt1.clone()), + make_candidate_backed_event(candidate_receipt2.clone()), + ], ) .await; - let valid_vote2 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(3), - candidate_hash2, - session, - true, - ) - .await; + let (valid_vote1, invalid_vote1) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(3), + ValidatorIndex(1), + candidate_hash1, + session, + VoteType::Explicit, + ) + .await; - let invalid_vote2 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash2, - session, - false, - ) - .await; + let (valid_vote2, invalid_vote2) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(3), + ValidatorIndex(1), + candidate_hash2, + session, + VoteType::Explicit, + ) + .await; virtual_overseer .send(FromOrchestra::Communication { @@ -880,7 +958,10 @@ fn dispute_gets_confirmed_via_participation() { }) .await; - assert_eq!(rx.await.unwrap(), vec![(session, candidate_hash1)]); + assert_eq!( + rx.await.unwrap(), + vec![(session, candidate_hash1, DisputeStatus::Active)] + ); let (tx, rx) = oneshot::channel(); virtual_overseer @@ -893,7 +974,7 @@ fn dispute_gets_confirmed_via_participation() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 2); + assert_eq!(votes.valid.raw().len(), 2); assert_eq!(votes.invalid.len(), 1); } @@ -928,7 +1009,7 @@ fn dispute_gets_confirmed_via_participation() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 1); + assert_eq!(votes.valid.raw().len(), 1); assert_eq!(votes.invalid.len(), 1); } @@ -958,61 +1039,39 @@ fn dispute_gets_confirmed_at_byzantine_threshold() { let candidate_receipt2 = make_invalid_candidate_receipt(); let candidate_hash2 = candidate_receipt2.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let valid_vote1 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(3), - candidate_hash1, - session, - true, - ) - .await; - - let invalid_vote1 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash1, - session, - false, - ) - .await; - - let valid_vote1a = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(4), - candidate_hash1, - session, - true, - ) + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) .await; - let invalid_vote1a = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(5), - candidate_hash1, - session, - false, - ) - .await; + let (valid_vote1, invalid_vote1) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(3), + ValidatorIndex(1), + candidate_hash1, + session, + VoteType::Explicit, + ) + .await; - let valid_vote2 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(3), - candidate_hash2, - session, - true, - ) - .await; + let (valid_vote1a, invalid_vote1a) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(4), + ValidatorIndex(5), + candidate_hash1, + session, + VoteType::Explicit, + ) + .await; - let invalid_vote2 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash2, - session, - false, - ) - .await; + let (valid_vote2, invalid_vote2) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(3), + ValidatorIndex(1), + candidate_hash2, + session, + VoteType::Explicit, + ) + .await; virtual_overseer .send(FromOrchestra::Communication { @@ -1032,7 +1091,8 @@ fn dispute_gets_confirmed_at_byzantine_threshold() { handle_approval_vote_request(&mut virtual_overseer, &candidate_hash1, HashMap::new()) .await; - participation_missing_availability(&mut virtual_overseer).await; + // Participation won't happen here because the dispute is neither backed, not confirmed + // nor the candidate is included. Or in other words - we'll refrain from participation. { let (tx, rx) = oneshot::channel(); @@ -1042,7 +1102,10 @@ fn dispute_gets_confirmed_at_byzantine_threshold() { }) .await; - assert_eq!(rx.await.unwrap(), vec![(session, candidate_hash1)]); + assert_eq!( + rx.await.unwrap(), + vec![(session, candidate_hash1, DisputeStatus::Confirmed)] + ); let (tx, rx) = oneshot::channel(); virtual_overseer @@ -1055,7 +1118,7 @@ fn dispute_gets_confirmed_at_byzantine_threshold() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 2); + assert_eq!(votes.valid.raw().len(), 2); assert_eq!(votes.invalid.len(), 2); } @@ -1090,7 +1153,7 @@ fn dispute_gets_confirmed_at_byzantine_threshold() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 1); + assert_eq!(votes.valid.raw().len(), 1); assert_eq!(votes.invalid.len(), 1); } @@ -1119,7 +1182,9 @@ fn backing_statements_import_works_and_no_spam() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) + .await; let valid_vote1 = test_state .issue_backing_statement_with_index(ValidatorIndex(3), candidate_hash, session) @@ -1167,7 +1232,7 @@ fn backing_statements_import_works_and_no_spam() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 2); + assert_eq!(votes.valid.raw().len(), 2); assert_eq!(votes.invalid.len(), 0); } @@ -1182,6 +1247,15 @@ fn backing_statements_import_works_and_no_spam() { .issue_backing_statement_with_index(ValidatorIndex(4), candidate_hash, session) .await; + test_state + .activate_leaf_at_session( + &mut virtual_overseer, + session, + 1, + vec![make_candidate_backed_event(candidate_receipt.clone())], + ) + .await; + let (pending_confirmation, confirmation_rx) = oneshot::channel(); // Backing vote import should not have accounted to spam slots, so this should succeed // as well: @@ -1223,25 +1297,24 @@ fn conflicting_votes_lead_to_dispute_participation() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(3), - candidate_hash, + test_state + .activate_leaf_at_session( + &mut virtual_overseer, session, - true, + 1, + vec![make_candidate_backed_event(candidate_receipt.clone())], ) .await; - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - false, - ) - .await; + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(3), + ValidatorIndex(1), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; let invalid_vote_2 = test_state .issue_explicit_statement_with_index( @@ -1283,7 +1356,10 @@ fn conflicting_votes_lead_to_dispute_participation() { }) .await; - assert_eq!(rx.await.unwrap(), vec![(session, candidate_hash)]); + assert_eq!( + rx.await.unwrap(), + vec![(session, candidate_hash, DisputeStatus::Active)] + ); let (tx, rx) = oneshot::channel(); virtual_overseer @@ -1296,7 +1372,7 @@ fn conflicting_votes_lead_to_dispute_participation() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 2); + assert_eq!(votes.valid.raw().len(), 2); assert_eq!(votes.invalid.len(), 1); } @@ -1323,7 +1399,7 @@ fn conflicting_votes_lead_to_dispute_participation() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 2); + assert_eq!(votes.valid.raw().len(), 2); assert_eq!(votes.invalid.len(), 2); } @@ -1348,7 +1424,14 @@ fn positive_votes_dont_trigger_participation() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; + test_state + .activate_leaf_at_session( + &mut virtual_overseer, + session, + 1, + vec![make_candidate_backed_event(candidate_receipt.clone())], + ) + .await; let valid_vote = test_state .issue_explicit_statement_with_index( @@ -1400,7 +1483,7 @@ fn positive_votes_dont_trigger_participation() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 1); + assert_eq!(votes.valid.raw().len(), 1); assert!(votes.invalid.is_empty()); } @@ -1436,7 +1519,7 @@ fn positive_votes_dont_trigger_participation() { .await; let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); - assert_eq!(votes.valid.len(), 2); + assert_eq!(votes.valid.raw().len(), 2); assert!(votes.invalid.is_empty()); } @@ -1461,25 +1544,19 @@ fn wrong_validator_index_is_ignored() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, - session, - true, - ) + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) .await; - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - false, - ) - .await; + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(2), + ValidatorIndex(1), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; virtual_overseer .send(FromOrchestra::Communication { @@ -1539,25 +1616,24 @@ fn finality_votes_ignore_disputed_candidates() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, + test_state + .activate_leaf_at_session( + &mut virtual_overseer, session, - true, + 1, + vec![make_candidate_backed_event(candidate_receipt.clone())], ) .await; - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - false, - ) - .await; + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(2), + ValidatorIndex(1), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; virtual_overseer .send(FromOrchestra::Communication { @@ -1649,28 +1725,27 @@ fn supermajority_valid_dispute_may_be_finalized() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let supermajority_threshold = - polkadot_primitives::v2::supermajority_threshold(test_state.validators.len()); - - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, + test_state + .activate_leaf_at_session( + &mut virtual_overseer, session, - true, + 1, + vec![make_candidate_backed_event(candidate_receipt.clone())], ) .await; - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - false, - ) - .await; + let supermajority_threshold = + polkadot_primitives::v2::supermajority_threshold(test_state.validators.len()); + + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(2), + ValidatorIndex(1), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; virtual_overseer .send(FromOrchestra::Communication { @@ -1789,28 +1864,27 @@ fn concluded_supermajority_for_non_active_after_time() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let supermajority_threshold = - polkadot_primitives::v2::supermajority_threshold(test_state.validators.len()); - - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, + test_state + .activate_leaf_at_session( + &mut virtual_overseer, session, - true, + 1, + vec![make_candidate_backed_event(candidate_receipt.clone())], ) .await; - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - false, - ) - .await; + let supermajority_threshold = + polkadot_primitives::v2::supermajority_threshold(test_state.validators.len()); + + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(2), + ValidatorIndex(1), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; virtual_overseer .send(FromOrchestra::Communication { @@ -1907,28 +1981,27 @@ fn concluded_supermajority_against_non_active_after_time() { let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let supermajority_threshold = - polkadot_primitives::v2::supermajority_threshold(test_state.validators.len()); - - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, + test_state + .activate_leaf_at_session( + &mut virtual_overseer, session, - true, + 1, + vec![make_candidate_backed_event(candidate_receipt.clone())], ) .await; - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - false, - ) - .await; + let supermajority_threshold = + polkadot_primitives::v2::supermajority_threshold(test_state.validators.len()); + + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(2), + ValidatorIndex(1), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; let (pending_confirmation, confirmation_rx) = oneshot::channel(); virtual_overseer @@ -2031,25 +2104,19 @@ fn resume_dispute_without_local_statement() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - true, - ) + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) .await; - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, - session, - false, - ) - .await; + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(1), + ValidatorIndex(2), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; let (pending_confirmation, confirmation_rx) = oneshot::channel(); virtual_overseer @@ -2069,7 +2136,8 @@ fn resume_dispute_without_local_statement() { .await; // Missing availability -> No local vote. - participation_missing_availability(&mut virtual_overseer).await; + // Participation won't happen here because the dispute is neither backed, not confirmed + // nor the candidate is included. Or in other words - we'll refrain from participation. assert_eq!(confirmation_rx.await, Ok(ImportStatementsResult::ValidImport)); @@ -2107,68 +2175,27 @@ fn resume_dispute_without_local_statement() { ) .await; - let valid_vote0 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(0), - candidate_hash, - session, - true, - ) - .await; - let valid_vote3 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(3), - candidate_hash, - session, - true, - ) - .await; - let valid_vote4 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(4), - candidate_hash, - session, - true, - ) - .await; - let valid_vote5 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(5), - candidate_hash, - session, - true, - ) - .await; - let valid_vote6 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(6), - candidate_hash, - session, - true, - ) - .await; - let valid_vote7 = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(7), - candidate_hash, - session, - true, - ) - .await; + let mut statements = Vec::new(); + // Getting votes for supermajority. Should already have two valid votes. + for i in vec![3, 4, 5, 6, 7] { + let vote = test_state + .issue_explicit_statement_with_index( + ValidatorIndex(i), + candidate_hash, + session, + true, + ) + .await; + + statements.push((vote, ValidatorIndex(i as _))); + } virtual_overseer .send(FromOrchestra::Communication { msg: DisputeCoordinatorMessage::ImportStatements { candidate_receipt: candidate_receipt.clone(), session, - statements: vec![ - (valid_vote0, ValidatorIndex(0)), - (valid_vote3, ValidatorIndex(3)), - (valid_vote4, ValidatorIndex(4)), - (valid_vote5, ValidatorIndex(5)), - (valid_vote6, ValidatorIndex(6)), - (valid_vote7, ValidatorIndex(7)), - ], + statements, pending_confirmation: None, }, }) @@ -2211,34 +2238,33 @@ fn resume_dispute_with_local_statement() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let local_valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(0), - candidate_hash, + test_state + .activate_leaf_at_session( + &mut virtual_overseer, session, - true, + 1, + vec![make_candidate_backed_event(candidate_receipt.clone())], ) .await; - let valid_vote = test_state + let local_valid_vote = test_state .issue_explicit_statement_with_index( - ValidatorIndex(1), + ValidatorIndex(0), candidate_hash, session, true, ) .await; - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, - session, - false, - ) - .await; + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(1), + ValidatorIndex(2), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; let (pending_confirmation, confirmation_rx) = oneshot::channel(); virtual_overseer @@ -2255,6 +2281,7 @@ fn resume_dispute_with_local_statement() { }, }) .await; + handle_approval_vote_request(&mut virtual_overseer, &candidate_hash, HashMap::new()) .await; @@ -2309,25 +2336,19 @@ fn resume_dispute_without_local_statement_or_local_key() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; - - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - true, - ) + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) .await; - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, - session, - false, - ) - .await; + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(1), + ValidatorIndex(2), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; let (pending_confirmation, confirmation_rx) = oneshot::channel(); virtual_overseer @@ -2402,7 +2423,9 @@ fn resume_dispute_with_local_statement_without_local_key() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) + .await; let local_valid_vote = test_state .issue_explicit_statement_with_index( @@ -2413,23 +2436,15 @@ fn resume_dispute_with_local_statement_without_local_key() { ) .await; - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - true, - ) - .await; - - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, - session, - false, - ) - .await; + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(1), + ValidatorIndex(2), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; let (pending_confirmation, confirmation_rx) = oneshot::channel(); virtual_overseer @@ -2469,6 +2484,7 @@ fn resume_dispute_with_local_statement_without_local_key() { test_state }) }); + // No keys: test_state.subsystem_keystore = make_keystore(vec![Sr25519Keyring::Two.to_seed()].into_iter()).into(); @@ -2510,7 +2526,9 @@ fn issue_local_statement_does_cause_distribution_but_not_duplicate_participation let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) + .await; let other_vote = test_state .issue_explicit_statement_with_index( @@ -2583,7 +2601,9 @@ fn own_approval_vote_gets_distributed_on_dispute() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) + .await; let statement = test_state.issue_approval_vote_with_index( ValidatorIndex(0), @@ -2604,22 +2624,15 @@ fn own_approval_vote_gets_distributed_on_dispute() { .await; // Trigger dispute: - let invalid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(1), - candidate_hash, - session, - false, - ) - .await; - let valid_vote = test_state - .issue_explicit_statement_with_index( - ValidatorIndex(2), - candidate_hash, - session, - true, - ) - .await; + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(2), + ValidatorIndex(1), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; let (pending_confirmation, confirmation_rx) = oneshot::channel(); virtual_overseer @@ -2674,7 +2687,9 @@ fn negative_issue_local_statement_only_triggers_import() { let candidate_receipt = make_invalid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) + .await; virtual_overseer .send(FromOrchestra::Communication { @@ -2687,6 +2702,12 @@ fn negative_issue_local_statement_only_triggers_import() { }) .await; + // Assert that subsystem is not participating. + assert!(virtual_overseer.recv().timeout(TEST_TIMEOUT).await.is_none()); + + virtual_overseer.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; + assert!(virtual_overseer.try_recv().await.is_none()); + let backend = DbBackend::new( test_state.db.clone(), test_state.config.column_config(), @@ -2700,12 +2721,6 @@ fn negative_issue_local_statement_only_triggers_import() { let disputes = backend.load_recent_disputes().unwrap(); assert_eq!(disputes, None); - // Assert that subsystem is not participating. - assert!(virtual_overseer.recv().timeout(TEST_TIMEOUT).await.is_none()); - - virtual_overseer.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; - assert!(virtual_overseer.try_recv().await.is_none()); - test_state }) }); @@ -2722,7 +2737,9 @@ fn redundant_votes_ignored() { let candidate_receipt = make_valid_candidate_receipt(); let candidate_hash = candidate_receipt.hash(); - test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await; + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) + .await; let valid_vote = test_state .issue_backing_statement_with_index(ValidatorIndex(1), candidate_hash, session) @@ -2780,3 +2797,241 @@ fn redundant_votes_ignored() { }) }); } + +#[test] +/// Make sure no disputes are recorded when there are no opposing votes, even if we reached supermajority. +fn no_onesided_disputes() { + test_harness(|mut test_state, mut virtual_overseer| { + Box::pin(async move { + let session = 1; + + test_state.handle_resume_sync(&mut virtual_overseer, session).await; + + let candidate_receipt = make_valid_candidate_receipt(); + let candidate_hash = candidate_receipt.hash(); + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) + .await; + + let mut statements = Vec::new(); + for index in 1..10 { + statements.push(( + test_state + .issue_backing_statement_with_index( + ValidatorIndex(index), + candidate_hash, + session, + ) + .await, + ValidatorIndex(index), + )); + } + + let (pending_confirmation, confirmation_rx) = oneshot::channel(); + virtual_overseer + .send(FromOrchestra::Communication { + msg: DisputeCoordinatorMessage::ImportStatements { + candidate_receipt: candidate_receipt.clone(), + session, + statements, + pending_confirmation: Some(pending_confirmation), + }, + }) + .await; + assert_matches!(confirmation_rx.await, Ok(ImportStatementsResult::ValidImport)); + + // We should not have any active disputes now. + let (tx, rx) = oneshot::channel(); + virtual_overseer + .send(FromOrchestra::Communication { + msg: DisputeCoordinatorMessage::ActiveDisputes(tx), + }) + .await; + + assert!(rx.await.unwrap().is_empty()); + + virtual_overseer.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; + + // No more messages expected: + assert!(virtual_overseer.try_recv().await.is_none()); + + test_state + }) + }); +} + +#[test] +fn refrain_from_participation() { + test_harness(|mut test_state, mut virtual_overseer| { + Box::pin(async move { + let session = 1; + + test_state.handle_resume_sync(&mut virtual_overseer, session).await; + + let candidate_receipt = make_valid_candidate_receipt(); + let candidate_hash = candidate_receipt.hash(); + + // activate leaf - no backing/included event + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) + .await; + + // generate two votes + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(1), + ValidatorIndex(2), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; + + virtual_overseer + .send(FromOrchestra::Communication { + msg: DisputeCoordinatorMessage::ImportStatements { + candidate_receipt: candidate_receipt.clone(), + session, + statements: vec![ + (valid_vote, ValidatorIndex(1)), + (invalid_vote, ValidatorIndex(2)), + ], + pending_confirmation: None, + }, + }) + .await; + + handle_approval_vote_request(&mut virtual_overseer, &candidate_hash, HashMap::new()) + .await; + + { + let (tx, rx) = oneshot::channel(); + virtual_overseer + .send(FromOrchestra::Communication { + msg: DisputeCoordinatorMessage::ActiveDisputes(tx), + }) + .await; + + assert_eq!(rx.await.unwrap().len(), 1); + + let (tx, rx) = oneshot::channel(); + virtual_overseer + .send(FromOrchestra::Communication { + msg: DisputeCoordinatorMessage::QueryCandidateVotes( + vec![(session, candidate_hash)], + tx, + ), + }) + .await; + + let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); + assert_eq!(votes.valid.raw().len(), 1); + assert_eq!(votes.invalid.len(), 1); + } + + // activate leaf - no backing event + test_state + .activate_leaf_at_session(&mut virtual_overseer, session, 1, Vec::new()) + .await; + + virtual_overseer.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; + + // confirm that no participation request is made. + assert!(virtual_overseer.try_recv().await.is_none()); + + test_state + }) + }); +} + +/// We have got no `participation_for_backed_candidates` test because most of the other tests (e.g. +/// `dispute_gets_confirmed_via_participation`, `backing_statements_import_works_and_no_spam`) use +/// candidate backing event to trigger participation. If they pass - that case works. +#[test] +fn participation_for_included_candidates() { + test_harness(|mut test_state, mut virtual_overseer| { + Box::pin(async move { + let session = 1; + + test_state.handle_resume_sync(&mut virtual_overseer, session).await; + + let candidate_receipt = make_valid_candidate_receipt(); + let candidate_hash = candidate_receipt.hash(); + + // activate leaf - with candidate included event + test_state + .activate_leaf_at_session( + &mut virtual_overseer, + session, + 1, + vec![make_candidate_included_event(candidate_receipt.clone())], + ) + .await; + + // generate two votes + let (valid_vote, invalid_vote) = generate_opposing_votes_pair( + &test_state, + ValidatorIndex(1), + ValidatorIndex(2), + candidate_hash, + session, + VoteType::Explicit, + ) + .await; + + virtual_overseer + .send(FromOrchestra::Communication { + msg: DisputeCoordinatorMessage::ImportStatements { + candidate_receipt: candidate_receipt.clone(), + session, + statements: vec![ + (valid_vote, ValidatorIndex(1)), + (invalid_vote, ValidatorIndex(2)), + ], + pending_confirmation: None, + }, + }) + .await; + + handle_approval_vote_request(&mut virtual_overseer, &candidate_hash, HashMap::new()) + .await; + + participation_with_distribution( + &mut virtual_overseer, + &candidate_hash, + candidate_receipt.commitments_hash, + ) + .await; + + { + let (tx, rx) = oneshot::channel(); + virtual_overseer + .send(FromOrchestra::Communication { + msg: DisputeCoordinatorMessage::ActiveDisputes(tx), + }) + .await; + + assert_eq!(rx.await.unwrap().len(), 1); + + // check if we have participated (casted a vote) + let (tx, rx) = oneshot::channel(); + virtual_overseer + .send(FromOrchestra::Communication { + msg: DisputeCoordinatorMessage::QueryCandidateVotes( + vec![(session, candidate_hash)], + tx, + ), + }) + .await; + + let (_, _, votes) = rx.await.unwrap().get(0).unwrap().clone(); + assert_eq!(votes.valid.raw().len(), 2); // 2 => we have participated + assert_eq!(votes.invalid.len(), 1); + } + + virtual_overseer.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; + + test_state + }) + }); +} diff --git a/node/core/parachains-inherent/Cargo.toml b/node/core/parachains-inherent/Cargo.toml index 615a87c058cb..36727371981c 100644 --- a/node/core/parachains-inherent/Cargo.toml +++ b/node/core/parachains-inherent/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-node-core-parachains-inherent" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -11,7 +11,8 @@ gum = { package = "tracing-gum", path = "../../gum" } thiserror = "1.0.31" async-trait = "0.1.57" polkadot-node-subsystem = { path = "../../subsystem" } +polkadot-overseer = { path = "../../overseer" } polkadot-primitives = { path = "../../../primitives" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } diff --git a/node/core/parachains-inherent/src/lib.rs b/node/core/parachains-inherent/src/lib.rs index e9441d21aefe..7634522128e7 100644 --- a/node/core/parachains-inherent/src/lib.rs +++ b/node/core/parachains-inherent/src/lib.rs @@ -29,9 +29,8 @@ use polkadot_node_subsystem::{ errors::SubsystemError, messages::ProvisionerMessage, overseer::Handle, }; use polkadot_primitives::v2::{Block, Hash, InherentData as ParachainsInherentData}; -use sp_blockchain::HeaderBackend; use sp_runtime::generic::BlockId; -use std::time; +use std::{sync::Arc, time}; pub(crate) const LOG_TARGET: &str = "parachain::parachains-inherent"; @@ -39,22 +38,24 @@ pub(crate) const LOG_TARGET: &str = "parachain::parachains-inherent"; const PROVISIONER_TIMEOUT: time::Duration = core::time::Duration::from_millis(2500); /// Provides the parachains inherent data. -pub struct ParachainsInherentDataProvider { - inherent_data: ParachainsInherentData, +pub struct ParachainsInherentDataProvider> { + pub client: Arc, + pub overseer: polkadot_overseer::Handle, + pub parent: Hash, } -impl ParachainsInherentDataProvider { - /// Create a [`Self`] directly from some [`ParachainsInherentData`]. - pub fn from_data(inherent_data: ParachainsInherentData) -> Self { - Self { inherent_data } +impl> ParachainsInherentDataProvider { + /// Create a new [`Self`]. + pub fn new(client: Arc, overseer: polkadot_overseer::Handle, parent: Hash) -> Self { + ParachainsInherentDataProvider { client, overseer, parent } } /// Create a new instance of the [`ParachainsInherentDataProvider`]. - pub async fn create>( - client: &C, + pub async fn create( + client: Arc, mut overseer: Handle, parent: Hash, - ) -> Result { + ) -> Result { let pid = async { let (sender, receiver) = futures::channel::oneshot::channel(); gum::trace!( @@ -119,18 +120,28 @@ impl ParachainsInherentDataProvider { }, }; - Ok(Self { inherent_data }) + Ok(inherent_data) } } #[async_trait::async_trait] -impl sp_inherents::InherentDataProvider for ParachainsInherentDataProvider { - fn provide_inherent_data( +impl> sp_inherents::InherentDataProvider + for ParachainsInherentDataProvider +{ + async fn provide_inherent_data( &self, dst_inherent_data: &mut sp_inherents::InherentData, ) -> Result<(), sp_inherents::Error> { + let inherent_data = ParachainsInherentDataProvider::create( + self.client.clone(), + self.overseer.clone(), + self.parent, + ) + .await + .map_err(|e| sp_inherents::Error::Application(Box::new(e)))?; + dst_inherent_data - .put_data(polkadot_primitives::v2::PARACHAINS_INHERENT_IDENTIFIER, &self.inherent_data) + .put_data(polkadot_primitives::v2::PARACHAINS_INHERENT_IDENTIFIER, &inherent_data) } async fn try_handle_error( diff --git a/node/core/provisioner/Cargo.toml b/node/core/provisioner/Cargo.toml index fbaea19618f6..df7fdc1a9511 100644 --- a/node/core/provisioner/Cargo.toml +++ b/node/core/provisioner/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-node-core-provisioner" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } @@ -18,7 +18,7 @@ futures-timer = "3.0.2" fatality = "0.0.6" [dev-dependencies] -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../../primitives/test-helpers" } diff --git a/node/core/provisioner/src/disputes/prioritized_selection/mod.rs b/node/core/provisioner/src/disputes/prioritized_selection/mod.rs index 07426ef1a75b..8ac582bb1cc4 100644 --- a/node/core/provisioner/src/disputes/prioritized_selection/mod.rs +++ b/node/core/provisioner/src/disputes/prioritized_selection/mod.rs @@ -99,7 +99,7 @@ where ); // Fetch the onchain disputes. We'll do a prioritization based on them. - let onchain = match get_onchain_disputes(sender, leaf.hash.clone()).await { + let onchain = match get_onchain_disputes(sender, leaf.hash).await { Ok(r) => r, Err(GetOnchainDisputesError::NotSupported(runtime_api_err, relay_parent)) => { // Runtime version is checked before calling this method, so the error below should never happen! @@ -139,6 +139,13 @@ where onchain.len(), ); + // Filter out unconfirmed disputes. However if the dispute is already onchain - don't skip it. + // In this case we'd better push as much fresh votes as possible to bring it to conclusion faster. + let recent_disputes = recent_disputes + .into_iter() + .filter(|d| d.2.is_confirmed_concluded() || onchain.contains_key(&(d.0, d.1))) + .collect::>(); + let partitioned = partition_recent_disputes(recent_disputes, &onchain); metrics.on_partition_recent_disputes(&partitioned); @@ -209,7 +216,7 @@ where // Check if votes are within the limit for (session_index, candidate_hash, selected_votes) in votes { - let votes_len = selected_votes.valid.len() + selected_votes.invalid.len(); + let votes_len = selected_votes.valid.raw().len() + selected_votes.invalid.len(); if votes_len + total_votes_len > MAX_DISPUTE_VOTES_FORWARDED_TO_RUNTIME { // we are done - no more votes can be added return result diff --git a/node/core/provisioner/src/disputes/prioritized_selection/tests.rs b/node/core/provisioner/src/disputes/prioritized_selection/tests.rs index f76107dc65d4..982d19356e6a 100644 --- a/node/core/provisioner/src/disputes/prioritized_selection/tests.rs +++ b/node/core/provisioner/src/disputes/prioritized_selection/tests.rs @@ -393,7 +393,9 @@ impl TestDisputes { ValidDisputeStatementKind::Explicit, 0, local_votes_count, - ), + ) + .into_iter() + .collect(), invalid: BTreeMap::new(), }, ); @@ -426,7 +428,7 @@ impl TestDisputes { pub fn add_unconfirmed_disputes_concluded_onchain( &mut self, dispute_count: usize, - ) -> (u32, usize) { + ) -> (SessionIndex, usize) { let local_votes_count = self.validators_count * 90 / 100; let onchain_votes_count = self.validators_count * 80 / 100; let session_idx = 0; @@ -444,7 +446,7 @@ impl TestDisputes { pub fn add_unconfirmed_disputes_unconcluded_onchain( &mut self, dispute_count: usize, - ) -> (u32, usize) { + ) -> (SessionIndex, usize) { let local_votes_count = self.validators_count * 90 / 100; let onchain_votes_count = self.validators_count * 40 / 100; let session_idx = 1; @@ -459,22 +461,25 @@ impl TestDisputes { (session_idx, (local_votes_count - onchain_votes_count) * dispute_count) } - pub fn add_unconfirmed_disputes_unknown_onchain( + pub fn add_confirmed_disputes_unknown_onchain( &mut self, dispute_count: usize, - ) -> (u32, usize) { + ) -> (SessionIndex, usize) { let local_votes_count = self.validators_count * 90 / 100; let session_idx = 2; let lf = leaf(); let dummy_receipt = test_helpers::dummy_candidate_receipt(lf.hash.clone()); for _ in 0..dispute_count { - let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active); + let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Confirmed); self.add_offchain_dispute(d.clone(), local_votes_count, dummy_receipt.clone()); } (session_idx, local_votes_count * dispute_count) } - pub fn add_concluded_disputes_known_onchain(&mut self, dispute_count: usize) -> (u32, usize) { + pub fn add_concluded_disputes_known_onchain( + &mut self, + dispute_count: usize, + ) -> (SessionIndex, usize) { let local_votes_count = self.validators_count * 90 / 100; let onchain_votes_count = self.validators_count * 75 / 100; let session_idx = 3; @@ -488,7 +493,10 @@ impl TestDisputes { (session_idx, (local_votes_count - onchain_votes_count) * dispute_count) } - pub fn add_concluded_disputes_unknown_onchain(&mut self, dispute_count: usize) -> (u32, usize) { + pub fn add_concluded_disputes_unknown_onchain( + &mut self, + dispute_count: usize, + ) -> (SessionIndex, usize) { let local_votes_count = self.validators_count * 90 / 100; let session_idx = 4; let lf = leaf(); @@ -500,6 +508,40 @@ impl TestDisputes { (session_idx, local_votes_count * dispute_count) } + pub fn add_unconfirmed_disputes_known_onchain( + &mut self, + dispute_count: usize, + ) -> (SessionIndex, usize) { + let local_votes_count = self.validators_count * 10 / 100; + let onchain_votes_count = self.validators_count * 10 / 100; + let session_idx = 5; + let lf = leaf(); + let dummy_receipt = test_helpers::dummy_candidate_receipt(lf.hash.clone()); + for _ in 0..dispute_count { + let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active); + self.add_offchain_dispute(d.clone(), local_votes_count, dummy_receipt.clone()); + self.add_onchain_dispute(d, onchain_votes_count); + } + + (session_idx, (local_votes_count - onchain_votes_count) * dispute_count) + } + + pub fn add_unconfirmed_disputes_unknown_onchain( + &mut self, + dispute_count: usize, + ) -> (SessionIndex, usize) { + let local_votes_count = self.validators_count * 10 / 100; + let session_idx = 6; + let lf = leaf(); + let dummy_receipt = test_helpers::dummy_candidate_receipt(lf.hash.clone()); + for _ in 0..dispute_count { + let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active); + self.add_offchain_dispute(d.clone(), local_votes_count, dummy_receipt.clone()); + } + + (session_idx, local_votes_count * dispute_count) + } + fn generate_local_votes( statement_kind: T, start_idx: usize, @@ -554,9 +596,9 @@ fn normal_flow() { // concluded disputes known onchain - these should be ignored let (_, _) = input.add_concluded_disputes_known_onchain(DISPUTES_PER_BATCH); - // active disputes unknown onchain + // confirmed disputes unknown onchain let (second_idx, second_votes) = - input.add_unconfirmed_disputes_unknown_onchain(DISPUTES_PER_BATCH); + input.add_confirmed_disputes_unknown_onchain(DISPUTES_PER_BATCH); let metrics = metrics::Metrics::new_dummy(); let mut vote_queries: usize = 0; @@ -635,8 +677,8 @@ fn many_batches() { // concluded disputes known onchain input.add_concluded_disputes_known_onchain(DISPUTES_PER_PARTITION); - // active disputes unknown onchain - input.add_unconfirmed_disputes_unknown_onchain(DISPUTES_PER_PARTITION); + // confirmed disputes unknown onchain + input.add_confirmed_disputes_unknown_onchain(DISPUTES_PER_PARTITION); let metrics = metrics::Metrics::new_dummy(); let mut vote_queries: usize = 0; @@ -720,3 +762,30 @@ fn votes_above_limit() { ACCEPTABLE_RUNTIME_VOTES_QUERIES_COUNT ); } + +#[test] +fn unconfirmed_are_handled_correctly() { + const VALIDATOR_COUNT: usize = 10; + const DISPUTES_PER_PARTITION: usize = 50; + + let mut input = TestDisputes::new(VALIDATOR_COUNT); + + // Add unconfirmed known onchain -> this should be pushed + let (pushed_idx, _) = input.add_unconfirmed_disputes_known_onchain(DISPUTES_PER_PARTITION); + + // Add unconfirmed unknown onchain -> this should be ignored + input.add_unconfirmed_disputes_unknown_onchain(DISPUTES_PER_PARTITION); + + let metrics = metrics::Metrics::new_dummy(); + let mut vote_queries: usize = 0; + test_harness( + |r| mock_overseer(r, &mut input, &mut vote_queries), + |mut tx: TestSubsystemSender| async move { + let lf = leaf(); + let result = select_disputes(&mut tx, &metrics, &lf).await; + + assert!(result.len() == DISPUTES_PER_PARTITION); + result.iter().for_each(|d| assert!(d.session == pushed_idx)); + }, + ); +} diff --git a/node/core/provisioner/src/disputes/random_selection/mod.rs b/node/core/provisioner/src/disputes/random_selection/mod.rs index a25d3445ac6e..9a827475aa55 100644 --- a/node/core/provisioner/src/disputes/random_selection/mod.rs +++ b/node/core/provisioner/src/disputes/random_selection/mod.rs @@ -42,51 +42,35 @@ enum RequestType { } /// Request open disputes identified by `CandidateHash` and the `SessionIndex`. -async fn request_disputes( +/// Returns only confirmed/concluded disputes. The rest are filtered out. +async fn request_confirmed_disputes( sender: &mut impl overseer::ProvisionerSenderTrait, active_or_recent: RequestType, ) -> Vec<(SessionIndex, CandidateHash)> { - let disputes = match active_or_recent { - RequestType::Recent => { - let (tx, rx) = oneshot::channel(); - let msg = DisputeCoordinatorMessage::RecentDisputes(tx); - sender.send_unbounded_message(msg); - let recent_disputes = match rx.await { - Ok(r) => r, - Err(oneshot::Canceled) => { - gum::warn!( - target: LOG_TARGET, - "Channel closed: unable to gather {:?} disputes", - active_or_recent - ); - Vec::new() - }, - }; - recent_disputes - .into_iter() - .map(|(sesion_idx, candodate_hash, _)| (sesion_idx, candodate_hash)) - .collect::>() - }, - RequestType::Active => { - let (tx, rx) = oneshot::channel(); - let msg = DisputeCoordinatorMessage::ActiveDisputes(tx); - sender.send_unbounded_message(msg); - let active_disputes = match rx.await { - Ok(r) => r, - Err(oneshot::Canceled) => { - gum::warn!( - target: LOG_TARGET, - "Unable to gather {:?} disputes", - active_or_recent - ); - Vec::new() - }, - }; - active_disputes + let (tx, rx) = oneshot::channel(); + let msg = match active_or_recent { + RequestType::Recent => DisputeCoordinatorMessage::RecentDisputes(tx), + RequestType::Active => DisputeCoordinatorMessage::ActiveDisputes(tx), + }; + + sender.send_unbounded_message(msg); + let disputes = match rx.await { + Ok(r) => r, + Err(oneshot::Canceled) => { + gum::warn!( + target: LOG_TARGET, + "Channel closed: unable to gather {:?} disputes", + active_or_recent + ); + Vec::new() }, }; disputes + .into_iter() + .filter(|d| d.2.is_confirmed_concluded()) + .map(|d| (d.0, d.1)) + .collect() } /// Extend `acc` by `n` random, picks of not-yet-present in `acc` items of `recent` without repetition and additions of recent. @@ -132,7 +116,7 @@ where // In case of an overload condition, we limit ourselves to active disputes, and fill up to the // upper bound of disputes to pass to wasm `fn create_inherent_data`. // If the active ones are already exceeding the bounds, randomly select a subset. - let recent = request_disputes(sender, RequestType::Recent).await; + let recent = request_confirmed_disputes(sender, RequestType::Recent).await; let disputes = if recent.len() > MAX_DISPUTES_FORWARDED_TO_RUNTIME { gum::warn!( target: LOG_TARGET, @@ -140,7 +124,7 @@ where recent.len(), MAX_DISPUTES_FORWARDED_TO_RUNTIME ); - let mut active = request_disputes(sender, RequestType::Active).await; + let mut active = request_confirmed_disputes(sender, RequestType::Active).await; let n_active = active.len(); let active = if active.len() > MAX_DISPUTES_FORWARDED_TO_RUNTIME { let mut picked = Vec::with_capacity(MAX_DISPUTES_FORWARDED_TO_RUNTIME); diff --git a/node/core/provisioner/src/lib.rs b/node/core/provisioner/src/lib.rs index f669f9ddae2c..fcb65d66f286 100644 --- a/node/core/provisioner/src/lib.rs +++ b/node/core/provisioner/src/lib.rs @@ -183,7 +183,7 @@ fn handle_active_leaves_update( per_relay_parent.remove(deactivated); } - for leaf in update.activated { + if let Some(leaf) = update.activated { let delay_fut = Delay::new(PRE_PROPOSE_TIMEOUT).map(move |_| leaf.hash).boxed(); per_relay_parent.insert(leaf.hash, PerRelayParent::new(leaf)); inherent_delays.push(delay_fut); @@ -373,7 +373,7 @@ async fn send_inherent_data( let disputes = match has_required_runtime( from_job, - leaf.hash.clone(), + leaf.hash, PRIORITIZED_SELECTION_RUNTIME_VERSION_REQUIREMENT, ) .await @@ -506,7 +506,7 @@ fn select_availability_bitfields( bitfields.len() ); - selected.into_iter().map(|(_, b)| b).collect() + selected.into_values().collect() } /// Determine which cores are free, and then to the degree possible, pick a candidate appropriate to each free core. diff --git a/node/core/pvf-checker/Cargo.toml b/node/core/pvf-checker/Cargo.toml index 85749daaff50..b24d2378bc74 100644 --- a/node/core/pvf-checker/Cargo.toml +++ b/node/core/pvf-checker/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-node-core-pvf-checker" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -15,14 +15,14 @@ polkadot-primitives = { path = "../../../primitives" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-overseer = { path = "../../overseer" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers"} test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../../primitives/test-helpers" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures-timer = "3.0.2" diff --git a/node/core/pvf/Cargo.toml b/node/core/pvf/Cargo.toml index 7ba85a9d141f..52dc160b709d 100644 --- a/node/core/pvf/Cargo.toml +++ b/node/core/pvf/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-node-core-pvf" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [[bin]] name = "puppet_worker" @@ -13,6 +13,7 @@ always-assert = "0.1" async-std = { version = "1.11.0", features = ["attributes"] } async-process = "1.3.0" assert_matches = "1.4.0" +cpu-time = "1.0.0" futures = "0.3.21" futures-timer = "3.0.2" slotmap = "1.0" @@ -21,19 +22,22 @@ pin-project = "1.0.9" rand = "0.8.5" tempfile = "3.3.0" rayon = "1.5.1" + parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } + polkadot-parachain = { path = "../../../parachain" } polkadot-core-primitives = { path = "../../../core-primitives" } polkadot-node-metrics = { path = "../../metrics"} -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-executor-wasmtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-executor-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-wasm-interface = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } + +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-executor-wasmtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-executor-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-wasm-interface = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [dev-dependencies] adder = { package = "test-parachain-adder", path = "../../../parachain/test-parachains/adder" } diff --git a/node/core/pvf/src/artifacts.rs b/node/core/pvf/src/artifacts.rs index 49d1be75fed4..413d73b4c558 100644 --- a/node/core/pvf/src/artifacts.rs +++ b/node/core/pvf/src/artifacts.rs @@ -96,17 +96,31 @@ pub enum ArtifactState { /// That means that the artifact should be accessible through the path obtained by the artifact /// id (unless, it was removed externally). Prepared { - /// The time when the artifact was the last time needed. + /// The time when the artifact was last needed. /// /// This is updated when we get the heads up for this artifact or when we just discover /// this file. last_time_needed: SystemTime, + /// The CPU time that was taken preparing this artifact. + cpu_time_elapsed: Duration, }, /// A task to prepare this artifact is scheduled. - Preparing { waiting_for_response: Vec }, + Preparing { + /// List of result senders that are waiting for a response. + waiting_for_response: Vec, + /// The number of times this artifact has failed to prepare. + num_failures: u32, + }, /// The code couldn't be compiled due to an error. Such artifacts /// never reach the executor and stay in the host's memory. - FailedToProcess(PrepareError), + FailedToProcess { + /// Keep track of the last time that processing this artifact failed. + last_time_failed: SystemTime, + /// The number of times this artifact has failed to prepare. + num_failures: u32, + /// The last error encountered for preparation. + error: PrepareError, + }, } /// A container of all known artifact ids and their states. @@ -120,7 +134,7 @@ impl Artifacts { /// /// The recognized artifacts will be filled in the table and unrecognized will be removed. pub async fn new(cache_path: &Path) -> Self { - // Make sure that the cache path directory and all it's parents are created. + // Make sure that the cache path directory and all its parents are created. // First delete the entire cache. Nodes are long-running so this should populate shortly. let _ = async_std::fs::remove_dir_all(cache_path).await; let _ = async_std::fs::create_dir_all(cache_path).await; @@ -150,7 +164,7 @@ impl Artifacts { // See the precondition. always!(self .artifacts - .insert(artifact_id, ArtifactState::Preparing { waiting_for_response }) + .insert(artifact_id, ArtifactState::Preparing { waiting_for_response, num_failures: 0 }) .is_none()); } @@ -159,11 +173,16 @@ impl Artifacts { /// This function must be used only for brand-new artifacts and should never be used for /// replacing existing ones. #[cfg(test)] - pub fn insert_prepared(&mut self, artifact_id: ArtifactId, last_time_needed: SystemTime) { + pub fn insert_prepared( + &mut self, + artifact_id: ArtifactId, + last_time_needed: SystemTime, + cpu_time_elapsed: Duration, + ) { // See the precondition. always!(self .artifacts - .insert(artifact_id, ArtifactState::Prepared { last_time_needed }) + .insert(artifact_id, ArtifactState::Prepared { last_time_needed, cpu_time_elapsed }) .is_none()); } diff --git a/node/core/pvf/src/error.rs b/node/core/pvf/src/error.rs index 4aca2da4b3ba..ddcdb2561cfd 100644 --- a/node/core/pvf/src/error.rs +++ b/node/core/pvf/src/error.rs @@ -15,10 +15,11 @@ // along with Polkadot. If not, see . use parity_scale_codec::{Decode, Encode}; -use std::any::Any; +use std::{any::Any, time::Duration}; -/// Result of PVF preparation performed by the validation host. -pub type PrepareResult = Result<(), PrepareError>; +/// Result of PVF preparation performed by the validation host. Contains the elapsed CPU time if +/// successful +pub type PrepareResult = Result; /// An error that occurred during the prepare part of the PVF pipeline. #[derive(Debug, Clone, Encode, Decode)] diff --git a/node/core/pvf/src/execute/mod.rs b/node/core/pvf/src/execute/mod.rs index 86e1d79fc951..bc7f035a8b40 100644 --- a/node/core/pvf/src/execute/mod.rs +++ b/node/core/pvf/src/execute/mod.rs @@ -24,4 +24,4 @@ mod queue; mod worker; pub use queue::{start, ToQueue}; -pub use worker::worker_entrypoint; +pub use worker::{worker_entrypoint, Response as ExecuteResponse}; diff --git a/node/core/pvf/src/execute/queue.rs b/node/core/pvf/src/execute/queue.rs index 23ed115b7f09..72b6e450351b 100644 --- a/node/core/pvf/src/execute/queue.rs +++ b/node/core/pvf/src/execute/queue.rs @@ -225,9 +225,8 @@ fn handle_job_finish( result_tx: ResultSender, ) { let (idle_worker, result) = match outcome { - Outcome::Ok { result_descriptor, duration_ms, idle_worker } => { + Outcome::Ok { result_descriptor, duration: _, idle_worker } => { // TODO: propagate the soft timeout - drop(duration_ms); (Some(idle_worker), Ok(result_descriptor)) }, @@ -247,13 +246,13 @@ fn handle_job_finish( gum::debug!( target: LOG_TARGET, validation_code_hash = ?artifact_id.code_hash, + ?worker, worker_rip = idle_worker.is_none(), - ?result, - "job finished.", + "execute worker concluded", ); - // First we send the result. It may fail due the other end of the channel being dropped, that's - // legitimate and we don't treat that as an error. + // 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); // Then, we should deal with the worker: @@ -305,7 +304,7 @@ async fn spawn_worker_task(program_path: PathBuf, spawn_timeout: Duration) -> Qu Err(err) => { gum::warn!(target: LOG_TARGET, "failed to spawn an execute worker: {:?}", err); - // Assume that the failure intermittent and retry after a delay. + // Assume that the failure is intermittent and retry after a delay. Delay::new(Duration::from_secs(3)).await; }, } diff --git a/node/core/pvf/src/execute/worker.rs b/node/core/pvf/src/execute/worker.rs index a0b8337ddc4a..105accf18e2b 100644 --- a/node/core/pvf/src/execute/worker.rs +++ b/node/core/pvf/src/execute/worker.rs @@ -18,8 +18,9 @@ use crate::{ artifacts::ArtifactPathId, executor_intf::Executor, worker_common::{ - bytes_to_path, framed_recv, framed_send, path_to_bytes, spawn_with_program_path, - worker_event_loop, IdleWorker, SpawnErr, WorkerHandle, + bytes_to_path, cpu_time_monitor_loop, framed_recv, framed_send, path_to_bytes, + spawn_with_program_path, worker_event_loop, IdleWorker, JobKind, SpawnErr, WorkerHandle, + JOB_TIMEOUT_WALL_CLOCK_FACTOR, }, LOG_TARGET, }; @@ -27,12 +28,21 @@ use async_std::{ io, os::unix::net::UnixStream, path::{Path, PathBuf}, + task, }; +use cpu_time::ProcessTime; use futures::FutureExt; use futures_timer::Delay; use parity_scale_codec::{Decode, Encode}; use polkadot_parachain::primitives::ValidationResult; -use std::time::{Duration, Instant}; +use std::{ + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + thread, + time::Duration, +}; /// Spawns a new worker with the given program path that acts as the worker and the spawn timeout. /// @@ -48,7 +58,7 @@ pub async fn spawn( pub enum Outcome { /// PVF execution completed successfully and the result is returned. The worker is ready for /// another job. - Ok { result_descriptor: ValidationResult, duration_ms: u64, idle_worker: IdleWorker }, + Ok { result_descriptor: ValidationResult, duration: Duration, idle_worker: IdleWorker }, /// The candidate validation failed. It may be for example because the wasm execution triggered a trap. /// Errors related to the preparation process are not expected to be encountered by the execution workers. InvalidCandidate { err: String, idle_worker: IdleWorker }, @@ -64,6 +74,8 @@ pub enum Outcome { /// Given the idle token of a worker and parameters of work, communicates with the worker and /// returns the outcome. +/// +/// NOTE: Returning the `HardTimeout` or `IoErr` errors will trigger the child process being killed. pub async fn start_work( worker: IdleWorker, artifact: ArtifactPathId, @@ -80,7 +92,9 @@ pub async fn start_work( artifact.path.display(), ); - if let Err(error) = send_request(&mut stream, &artifact.path, &validation_params).await { + if let Err(error) = + send_request(&mut stream, &artifact.path, &validation_params, execution_timeout).await + { gum::warn!( target: LOG_TARGET, worker_pid = %pid, @@ -91,6 +105,12 @@ pub async fn start_work( return Outcome::IoErr } + // We use a generous timeout here. This is in addition to the one in the child process, in + // case the child stalls. We have a wall clock timeout here in the host, but a CPU timeout + // in the child. We want to use CPU time because it varies less than wall clock time under + // load, but the CPU resources of the child can only be measured from the parent after the + // child process terminates. + let timeout = execution_timeout * JOB_TIMEOUT_WALL_CLOCK_FACTOR; let response = futures::select! { response = recv_response(&mut stream).fuse() => { match response { @@ -104,25 +124,47 @@ pub async fn start_work( ); return Outcome::IoErr }, - Ok(response) => response, + Ok(response) => { + if let Response::Ok{duration, ..} = response { + if duration > execution_timeout { + // The job didn't complete within the timeout. + gum::warn!( + target: LOG_TARGET, + worker_pid = %pid, + "execute job took {}ms cpu time, exceeded execution timeout {}ms.", + duration.as_millis(), + execution_timeout.as_millis(), + ); + + // Return a timeout error. + return Outcome::HardTimeout; + } + } + + response + }, } }, - _ = Delay::new(execution_timeout).fuse() => { + _ = Delay::new(timeout).fuse() => { gum::warn!( target: LOG_TARGET, worker_pid = %pid, validation_code_hash = ?artifact.id.code_hash, - "execution worker exceeded alloted time for execution", + "execution worker exceeded allotted time for execution", ); - return Outcome::HardTimeout; + // TODO: This case is not really a hard timeout as the timeout here in the host is + // lenient. Should fix this as part of + // https://github.com/paritytech/polkadot/issues/3754. + Response::TimedOut }, }; match response { - Response::Ok { result_descriptor, duration_ms } => - Outcome::Ok { result_descriptor, duration_ms, idle_worker: IdleWorker { stream, pid } }, + Response::Ok { result_descriptor, duration } => + Outcome::Ok { result_descriptor, duration, idle_worker: IdleWorker { stream, pid } }, Response::InvalidCandidate(err) => Outcome::InvalidCandidate { err, idle_worker: IdleWorker { stream, pid } }, + Response::TimedOut => Outcome::HardTimeout, Response::InternalError(err) => Outcome::InternalError { err, idle_worker: IdleWorker { stream, pid } }, } @@ -132,12 +174,14 @@ async fn send_request( stream: &mut UnixStream, artifact_path: &Path, validation_params: &[u8], + execution_timeout: Duration, ) -> io::Result<()> { framed_send(stream, path_to_bytes(artifact_path)).await?; - framed_send(stream, validation_params).await + framed_send(stream, validation_params).await?; + framed_send(stream, &execution_timeout.encode()).await } -async fn recv_request(stream: &mut UnixStream) -> io::Result<(PathBuf, Vec)> { +async fn recv_request(stream: &mut UnixStream) -> io::Result<(PathBuf, Vec, Duration)> { let artifact_path = framed_recv(stream).await?; let artifact_path = bytes_to_path(&artifact_path).ok_or_else(|| { io::Error::new( @@ -146,7 +190,14 @@ async fn recv_request(stream: &mut UnixStream) -> io::Result<(PathBuf, Vec)> ) })?; let params = framed_recv(stream).await?; - Ok((artifact_path, params)) + let execution_timeout = framed_recv(stream).await?; + let execution_timeout = Duration::decode(&mut &execution_timeout[..]).map_err(|_| { + io::Error::new( + io::ErrorKind::Other, + "execute pvf recv_request: failed to decode duration".to_string(), + ) + })?; + Ok((artifact_path, params, execution_timeout)) } async fn send_response(stream: &mut UnixStream, response: Response) -> io::Result<()> { @@ -164,9 +215,10 @@ async fn recv_response(stream: &mut UnixStream) -> io::Result { } #[derive(Encode, Decode)] -enum Response { - Ok { result_descriptor: ValidationResult, duration_ms: u64 }, +pub enum Response { + Ok { result_descriptor: ValidationResult, duration: Duration }, InvalidCandidate(String), + TimedOut, InternalError(String), } @@ -187,15 +239,53 @@ pub fn worker_entrypoint(socket_path: &str) { let executor = Executor::new().map_err(|e| { io::Error::new(io::ErrorKind::Other, format!("cannot create executor: {}", e)) })?; + loop { - let (artifact_path, params) = recv_request(&mut stream).await?; + let (artifact_path, params, execution_timeout) = recv_request(&mut stream).await?; gum::debug!( target: LOG_TARGET, worker_pid = %std::process::id(), "worker: validating artifact {}", artifact_path.display(), ); - let response = validate_using_artifact(&artifact_path, ¶ms, &executor).await; + + // Create a lock flag. We set it when either thread finishes. + let lock = Arc::new(AtomicBool::new(false)); + let cpu_time_start = ProcessTime::now(); + + // Spawn a new thread that runs the CPU time monitor. Continuously wakes up from + // sleeping and then either sleeps for the remaining CPU time, or kills the process if + // we exceed the CPU timeout. + let (stream_2, cpu_time_start_2, execution_timeout_2, lock_2) = + (stream.clone(), cpu_time_start, execution_timeout, lock.clone()); + let handle = + thread::Builder::new().name("CPU time monitor".into()).spawn(move || { + task::block_on(async { + cpu_time_monitor_loop( + JobKind::Execute, + stream_2, + cpu_time_start_2, + execution_timeout_2, + lock_2, + ) + .await; + }) + })?; + + let response = + validate_using_artifact(&artifact_path, ¶ms, &executor, cpu_time_start).await; + + let lock_result = + lock.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed); + if lock_result.is_err() { + // The other thread is still sending an error response over the socket. Wait on it + // and return. + let _ = handle.join(); + // Monitor thread detected timeout and likely already terminated the process, + // nothing to do. + continue + } + send_response(&mut stream, response).await?; } }); @@ -205,19 +295,19 @@ async fn validate_using_artifact( artifact_path: &Path, params: &[u8], executor: &Executor, + cpu_time_start: ProcessTime, ) -> Response { - let validation_started_at = Instant::now(); let descriptor_bytes = match unsafe { // SAFETY: this should be safe since the compiled artifact passed here comes from the // file created by the prepare workers. These files are obtained by calling // [`executor_intf::prepare`]. executor.execute(artifact_path.as_ref(), params) } { - Err(err) => return Response::format_invalid("execute", &err.to_string()), + Err(err) => return Response::format_invalid("execute", &err), Ok(d) => d, }; - let duration_ms = validation_started_at.elapsed().as_millis() as u64; + let duration = cpu_time_start.elapsed(); let result_descriptor = match ValidationResult::decode(&mut &descriptor_bytes[..]) { Err(err) => @@ -225,5 +315,5 @@ async fn validate_using_artifact( Ok(r) => r, }; - Response::Ok { result_descriptor, duration_ms } + Response::Ok { result_descriptor, duration } } diff --git a/node/core/pvf/src/executor_intf.rs b/node/core/pvf/src/executor_intf.rs index 55e94922ed26..c5578f5f81ad 100644 --- a/node/core/pvf/src/executor_intf.rs +++ b/node/core/pvf/src/executor_intf.rs @@ -96,7 +96,7 @@ pub fn prevalidate(code: &[u8]) -> Result Result, sc_executor_common::error::WasmError> { sc_executor_wasmtime::prepare_runtime_artifact(blob, &CONFIG.semantics) } @@ -129,7 +129,7 @@ impl Executor { // 2. It cannot and does not limit the stack space consumed by Rust code. // // Meaning that if the wasm code leaves no stack space for Rust code, then the Rust code - // and that will abort the process as well. + // will abort and that will abort the process as well. // // Typically on Linux the main thread gets the stack size specified by the `ulimit` and // typically it's configured to 8 MiB. Rust's spawned threads are 2 MiB. OTOH, the @@ -424,7 +424,7 @@ impl sp_core::traits::ReadRuntimeVersion for ReadRuntimeVersion { use parity_scale_codec::Encode; Ok(version.encode()) }, - None => Err(format!("runtime version section is not found")), + None => Err("runtime version section is not found".to_string()), } } } diff --git a/node/core/pvf/src/host.rs b/node/core/pvf/src/host.rs index 6670ea48d4ec..0f2e2b839a80 100644 --- a/node/core/pvf/src/host.rs +++ b/node/core/pvf/src/host.rs @@ -22,6 +22,7 @@ use crate::{ artifacts::{ArtifactId, ArtifactPathId, ArtifactState, Artifacts}, + error::PrepareError, execute, metrics::Metrics, prepare, PrepareResult, Priority, Pvf, ValidationError, LOG_TARGET, @@ -38,15 +39,26 @@ use std::{ time::{Duration, SystemTime}, }; -/// The time period after which the precheck preparation worker is considered unresponsive and will -/// be killed. +/// For prechecking requests, the time period after which the preparation worker is considered +/// unresponsive and will be killed. // NOTE: If you change this make sure to fix the buckets of `pvf_preparation_time` metric. -pub const PRECHECK_COMPILATION_TIMEOUT: Duration = Duration::from_secs(60); +pub const PRECHECK_PREPARATION_TIMEOUT: Duration = Duration::from_secs(60); -/// The time period after which the execute preparation worker is considered unresponsive and will -/// be killed. +/// For execution and heads-up requests, the time period after which the preparation worker is +/// considered unresponsive and will be killed. More lenient than the timeout for prechecking to +/// prevent honest validators from timing out on valid PVFs. // NOTE: If you change this make sure to fix the buckets of `pvf_preparation_time` metric. -pub const EXECUTE_COMPILATION_TIMEOUT: Duration = Duration::from_secs(180); +pub const LENIENT_PREPARATION_TIMEOUT: Duration = Duration::from_secs(360); + +/// The time period after which a failed preparation artifact is considered ready to be retried. +/// Note that we will only retry if another request comes in after this cooldown has passed. +#[cfg(not(test))] +pub const PREPARE_FAILURE_COOLDOWN: Duration = Duration::from_secs(15 * 60); +#[cfg(test)] +pub const PREPARE_FAILURE_COOLDOWN: Duration = Duration::from_millis(200); + +/// The amount of times we will retry failed prepare jobs. +pub const NUM_PREPARE_RETRIES: u32 = 5; /// An alias to not spell the type for the oneshot sender for the PVF execution result. pub(crate) type ResultSender = oneshot::Sender>; @@ -96,7 +108,13 @@ impl ValidationHost { result_tx: ResultSender, ) -> Result<(), String> { self.to_host_tx - .send(ToHost::ExecutePvf { pvf, execution_timeout, params, priority, result_tx }) + .send(ToHost::ExecutePvf(ExecutePvfInputs { + pvf, + execution_timeout, + params, + priority, + result_tx, + })) .await .map_err(|_| "the inner loop hung up".to_string()) } @@ -116,20 +134,17 @@ impl ValidationHost { } enum ToHost { - PrecheckPvf { - pvf: Pvf, - result_tx: PrepareResultSender, - }, - ExecutePvf { - pvf: Pvf, - execution_timeout: Duration, - params: Vec, - priority: Priority, - result_tx: ResultSender, - }, - HeadsUp { - active_pvfs: Vec, - }, + PrecheckPvf { pvf: Pvf, result_tx: PrepareResultSender }, + ExecutePvf(ExecutePvfInputs), + HeadsUp { active_pvfs: Vec }, +} + +struct ExecutePvfInputs { + pvf: Pvf, + execution_timeout: Duration, + params: Vec, + priority: Priority, + result_tx: ResultSender, } /// Configuration for the validation host. @@ -203,7 +218,7 @@ pub fn start(config: Config, metrics: Metrics) -> (ValidationHost, impl Future to_host, }; + // If the artifact failed before, it could be re-scheduled for preparation here if + // the preparation failure cooldown has elapsed. break_if_fatal!(handle_to_host( &cache_path, &mut artifacts, @@ -373,12 +390,12 @@ async fn run( from_prepare_queue = from_prepare_queue_rx.next() => { let from_queue = break_if_fatal!(from_prepare_queue.ok_or(Fatal)); - // Note that preparation always succeeds. + // Note that the preparation outcome is always reported as concluded. // // That's because the error conditions are written into the artifact and will be - // reported at the time of the execution. It potentially, but not necessarily, - // can be scheduled as a result of this function call, in case there are pending - // executions. + // reported at the time of the execution. It potentially, but not necessarily, can + // be scheduled for execution as a result of this function call, in case there are + // pending executions. // // We could be eager in terms of reporting and plumb the result from the preparation // worker but we don't for the sake of simplicity. @@ -406,32 +423,29 @@ async fn handle_to_host( ToHost::PrecheckPvf { pvf, result_tx } => { handle_precheck_pvf(artifacts, prepare_queue, pvf, result_tx).await?; }, - ToHost::ExecutePvf { pvf, execution_timeout, params, priority, result_tx } => { + ToHost::ExecutePvf(inputs) => { handle_execute_pvf( cache_path, artifacts, prepare_queue, execute_queue, awaiting_prepare, - pvf, - execution_timeout, - params, - priority, - result_tx, + inputs, ) .await?; }, - ToHost::HeadsUp { active_pvfs } => { - handle_heads_up(artifacts, prepare_queue, active_pvfs).await?; - }, + ToHost::HeadsUp { active_pvfs } => + handle_heads_up(artifacts, prepare_queue, active_pvfs).await?, } Ok(()) } -/// Handles PVF prechecking. +/// Handles PVF prechecking requests. /// -/// This tries to prepare the PVF by compiling the WASM blob within a given timeout ([`PRECHECK_COMPILATION_TIMEOUT`]). +/// This tries to prepare the PVF by compiling the WASM blob within a given timeout ([`PRECHECK_PREPARATION_TIMEOUT`]). +/// +/// If the prepare job failed previously, we may retry it under certain conditions. async fn handle_precheck_pvf( artifacts: &mut Artifacts, prepare_queue: &mut mpsc::Sender, @@ -442,14 +456,16 @@ async fn handle_precheck_pvf( if let Some(state) = artifacts.artifact_state_mut(&artifact_id) { match state { - ArtifactState::Prepared { last_time_needed } => { + ArtifactState::Prepared { last_time_needed, cpu_time_elapsed } => { *last_time_needed = SystemTime::now(); - let _ = result_sender.send(Ok(())); + let _ = result_sender.send(Ok(*cpu_time_elapsed)); }, - ArtifactState::Preparing { waiting_for_response } => + ArtifactState::Preparing { waiting_for_response, num_failures: _ } => waiting_for_response.push(result_sender), - ArtifactState::FailedToProcess(result) => { - let _ = result_sender.send(PrepareResult::Err(result.clone())); + ArtifactState::FailedToProcess { error, .. } => { + // Do not retry failed preparation if another pre-check request comes in. We do not retry pre-checking, + // anyway. + let _ = result_sender.send(PrepareResult::Err(error.clone())); }, } } else { @@ -459,7 +475,7 @@ async fn handle_precheck_pvf( prepare::ToQueue::Enqueue { priority: Priority::Normal, pvf, - compilation_timeout: PRECHECK_COMPILATION_TIMEOUT, + preparation_timeout: PRECHECK_PREPARATION_TIMEOUT, }, ) .await?; @@ -469,28 +485,30 @@ async fn handle_precheck_pvf( /// Handles PVF execution. /// -/// This will first try to prepare the PVF, if a prepared artifact does not already exist. If there is already a -/// preparation job, we coalesce the two preparation jobs. When preparing for execution, we use a more lenient timeout -/// ([`EXECUTE_COMPILATION_TIMEOUT`]) than when prechecking. +/// This will try to prepare the PVF, if a prepared artifact does not already exist. If there is already a +/// preparation job, we coalesce the two preparation jobs. +/// +/// If the prepare job failed previously, we may retry it under certain conditions. +/// +/// When preparing for execution, we use a more lenient timeout ([`EXECUTE_PREPARATION_TIMEOUT`]) +/// than when prechecking. async fn handle_execute_pvf( cache_path: &Path, artifacts: &mut Artifacts, prepare_queue: &mut mpsc::Sender, execute_queue: &mut mpsc::Sender, awaiting_prepare: &mut AwaitingPrepare, - pvf: Pvf, - execution_timeout: Duration, - params: Vec, - priority: Priority, - result_tx: ResultSender, + inputs: ExecutePvfInputs, ) -> Result<(), Fatal> { + let ExecutePvfInputs { pvf, execution_timeout, params, priority, result_tx } = inputs; let artifact_id = pvf.as_artifact_id(); if let Some(state) = artifacts.artifact_state_mut(&artifact_id) { match state { - ArtifactState::Prepared { last_time_needed } => { + ArtifactState::Prepared { last_time_needed, .. } => { *last_time_needed = SystemTime::now(); + // This artifact has already been prepared, send it to the execute queue. send_execute( execute_queue, execute::ToQueue::Enqueue { @@ -502,11 +520,29 @@ async fn handle_execute_pvf( ) .await?; }, - ArtifactState::Preparing { waiting_for_response: _ } => { + ArtifactState::Preparing { .. } => { awaiting_prepare.add(artifact_id, execution_timeout, params, result_tx); }, - ArtifactState::FailedToProcess(error) => { - let _ = result_tx.send(Err(ValidationError::from(error.clone()))); + ArtifactState::FailedToProcess { last_time_failed, num_failures, error } => { + if can_retry_prepare_after_failure(*last_time_failed, *num_failures, error) { + // If we are allowed to retry the failed prepare job, change the state to + // Preparing and re-queue this job. + *state = ArtifactState::Preparing { + waiting_for_response: Vec::new(), + num_failures: *num_failures, + }; + send_prepare( + prepare_queue, + prepare::ToQueue::Enqueue { + priority, + pvf, + preparation_timeout: LENIENT_PREPARATION_TIMEOUT, + }, + ) + .await?; + } else { + let _ = result_tx.send(Err(ValidationError::from(error.clone()))); + } }, } } else { @@ -518,15 +554,16 @@ async fn handle_execute_pvf( prepare::ToQueue::Enqueue { priority, pvf, - compilation_timeout: EXECUTE_COMPILATION_TIMEOUT, + preparation_timeout: LENIENT_PREPARATION_TIMEOUT, }, ) .await?; + // Add an execution request that will wait to run after this prepare job has finished. awaiting_prepare.add(artifact_id, execution_timeout, params, result_tx); } - return Ok(()) + Ok(()) } async fn handle_heads_up( @@ -543,10 +580,28 @@ async fn handle_heads_up( ArtifactState::Prepared { last_time_needed, .. } => { *last_time_needed = now; }, - ArtifactState::Preparing { waiting_for_response: _ } => { + ArtifactState::Preparing { .. } => { // The artifact is already being prepared, so we don't need to do anything. }, - ArtifactState::FailedToProcess(_) => {}, + ArtifactState::FailedToProcess { last_time_failed, num_failures, error } => { + if can_retry_prepare_after_failure(*last_time_failed, *num_failures, error) { + // If we are allowed to retry the failed prepare job, change the state to + // Preparing and re-queue this job. + *state = ArtifactState::Preparing { + waiting_for_response: vec![], + num_failures: *num_failures, + }; + send_prepare( + prepare_queue, + prepare::ToQueue::Enqueue { + priority: Priority::Normal, + pvf: active_pvf, + preparation_timeout: LENIENT_PREPARATION_TIMEOUT, + }, + ) + .await?; + } + }, } } else { // It's not in the artifacts, so we need to enqueue a job to prepare it. @@ -557,7 +612,7 @@ async fn handle_heads_up( prepare::ToQueue::Enqueue { priority: Priority::Normal, pvf: active_pvf, - compilation_timeout: EXECUTE_COMPILATION_TIMEOUT, + preparation_timeout: LENIENT_PREPARATION_TIMEOUT, }, ) .await?; @@ -596,20 +651,26 @@ async fn handle_prepare_done( never!("the artifact is already prepared: {:?}", artifact_id); return Ok(()) }, - Some(ArtifactState::FailedToProcess(_)) => { + Some(ArtifactState::FailedToProcess { .. }) => { // The reasoning is similar to the above, the artifact cannot be // processed at this point. never!("the artifact is already processed unsuccessfully: {:?}", artifact_id); return Ok(()) }, - Some(state @ ArtifactState::Preparing { waiting_for_response: _ }) => state, + Some(state @ ArtifactState::Preparing { .. }) => state, }; - if let ArtifactState::Preparing { waiting_for_response } = state { + let num_failures = if let ArtifactState::Preparing { waiting_for_response, num_failures } = + state + { for result_sender in waiting_for_response.drain(..) { let _ = result_sender.send(result.clone()); } - } + num_failures + } else { + never!("The reasoning is similar to the above, the artifact can only be preparing at this point; qed"); + return Ok(()) + }; // It's finally time to dispatch all the execution requests that were waiting for this artifact // to be prepared. @@ -640,8 +701,13 @@ async fn handle_prepare_done( } *state = match result { - Ok(()) => ArtifactState::Prepared { last_time_needed: SystemTime::now() }, - Err(error) => ArtifactState::FailedToProcess(error.clone()), + Ok(cpu_time_elapsed) => + ArtifactState::Prepared { last_time_needed: SystemTime::now(), cpu_time_elapsed }, + Err(error) => ArtifactState::FailedToProcess { + last_time_failed: SystemTime::now(), + num_failures: *num_failures + 1, + error, + }, }; Ok(()) @@ -704,6 +770,24 @@ async fn sweeper_task(mut sweeper_rx: mpsc::Receiver) { } } +/// Check if the conditions to retry a prepare job have been met. +fn can_retry_prepare_after_failure( + last_time_failed: SystemTime, + num_failures: u32, + error: &PrepareError, +) -> bool { + use PrepareError::*; + match error { + // Gracefully returned an error, so it will probably be reproducible. Don't retry. + Prevalidation(_) | Preparation(_) => false, + // Retry if the retry cooldown has elapsed and if we have already retried less than + // `NUM_PREPARE_RETRIES` times. IO errors may resolve themselves. + Panic(_) | TimedOut | DidNotMakeIt => + SystemTime::now() >= last_time_failed + PREPARE_FAILURE_COOLDOWN && + num_failures <= NUM_PREPARE_RETRIES, + } +} + /// A stream that yields a pulse continuously at a given interval. fn pulse_every(interval: std::time::Duration) -> impl futures::Stream { futures::stream::unfold(interval, { @@ -831,6 +915,25 @@ mod tests { .await } + async fn poll_ensure_to_prepare_queue_is_empty(&mut self) { + use futures_timer::Delay; + + let to_prepare_queue_rx = &mut self.to_prepare_queue_rx; + run_until( + &mut self.run, + async { + futures::select! { + _ = Delay::new(Duration::from_millis(500)).fuse() => (), + _ = to_prepare_queue_rx.next().fuse() => { + panic!("the prepare queue is supposed to be empty") + } + } + } + .boxed(), + ) + .await + } + async fn poll_ensure_to_execute_queue_is_empty(&mut self) { use futures_timer::Delay; @@ -841,7 +944,7 @@ mod tests { futures::select! { _ = Delay::new(Duration::from_millis(500)).fuse() => (), _ = to_execute_queue_rx.next().fuse() => { - panic!("the execute queue supposed to be empty") + panic!("the execute queue is supposed to be empty") } } } @@ -914,8 +1017,8 @@ mod tests { let mut builder = Builder::default(); builder.cleanup_pulse_interval = Duration::from_millis(100); builder.artifact_ttl = Duration::from_millis(500); - builder.artifacts.insert_prepared(artifact_id(1), mock_now); - builder.artifacts.insert_prepared(artifact_id(2), mock_now); + builder.artifacts.insert_prepared(artifact_id(1), mock_now, Duration::default()); + builder.artifacts.insert_prepared(artifact_id(2), mock_now, Duration::default()); let mut test = builder.build(); let mut host = test.host_handle(); @@ -985,7 +1088,10 @@ mod tests { ); test.from_prepare_queue_tx - .send(prepare::FromQueue { artifact_id: artifact_id(1), result: Ok(()) }) + .send(prepare::FromQueue { + artifact_id: artifact_id(1), + result: Ok(Duration::default()), + }) .await .unwrap(); let result_tx_pvf_1_1 = assert_matches!( @@ -998,7 +1104,10 @@ mod tests { ); test.from_prepare_queue_tx - .send(prepare::FromQueue { artifact_id: artifact_id(2), result: Ok(()) }) + .send(prepare::FromQueue { + artifact_id: artifact_id(2), + result: Ok(Duration::default()), + }) .await .unwrap(); let result_tx_pvf_2 = assert_matches!( @@ -1047,13 +1156,16 @@ mod tests { ); // Send `Ok` right away and poll the host. test.from_prepare_queue_tx - .send(prepare::FromQueue { artifact_id: artifact_id(1), result: Ok(()) }) + .send(prepare::FromQueue { + artifact_id: artifact_id(1), + result: Ok(Duration::default()), + }) .await .unwrap(); // No pending execute requests. test.poll_ensure_to_execute_queue_is_empty().await; // Received the precheck result. - assert_matches!(result_rx.now_or_never().unwrap().unwrap(), Ok(())); + assert_matches!(result_rx.now_or_never().unwrap().unwrap(), Ok(_)); // Send multiple requests for the same PVF. let mut precheck_receivers = Vec::new(); @@ -1151,7 +1263,10 @@ mod tests { prepare::ToQueue::Enqueue { .. } ); test.from_prepare_queue_tx - .send(prepare::FromQueue { artifact_id: artifact_id(2), result: Ok(()) }) + .send(prepare::FromQueue { + artifact_id: artifact_id(2), + result: Ok(Duration::default()), + }) .await .unwrap(); // The execute queue receives new request, preckecking is finished and we can @@ -1161,10 +1276,232 @@ mod tests { execute::ToQueue::Enqueue { .. } ); for result_rx in precheck_receivers { - assert_matches!(result_rx.now_or_never().unwrap().unwrap(), Ok(())); + assert_matches!(result_rx.now_or_never().unwrap().unwrap(), Ok(_)); } } + // Test that multiple prechecking requests do not trigger preparation retries if the first one + // failed. + #[async_std::test] + async fn test_precheck_prepare_retry() { + let mut test = Builder::default().build(); + let mut host = test.host_handle(); + + // Submit a precheck request that fails. + let (result_tx, _result_rx) = oneshot::channel(); + host.precheck_pvf(Pvf::from_discriminator(1), result_tx).await.unwrap(); + + // The queue received the prepare request. + assert_matches!( + test.poll_and_recv_to_prepare_queue().await, + prepare::ToQueue::Enqueue { .. } + ); + // Send a PrepareError. + test.from_prepare_queue_tx + .send(prepare::FromQueue { + artifact_id: artifact_id(1), + result: Err(PrepareError::TimedOut), + }) + .await + .unwrap(); + + // Submit another precheck request. + let (result_tx_2, _result_rx_2) = oneshot::channel(); + host.precheck_pvf(Pvf::from_discriminator(1), result_tx_2).await.unwrap(); + + // Assert the prepare queue is empty. + test.poll_ensure_to_prepare_queue_is_empty().await; + + // Pause for enough time to reset the cooldown for this failed prepare request. + futures_timer::Delay::new(PREPARE_FAILURE_COOLDOWN).await; + + // Submit another precheck request. + let (result_tx_3, _result_rx_3) = oneshot::channel(); + host.precheck_pvf(Pvf::from_discriminator(1), result_tx_3).await.unwrap(); + + // Assert the prepare queue is empty - we do not retry for precheck requests. + test.poll_ensure_to_prepare_queue_is_empty().await; + } + + // Test that multiple execution requests trigger preparation retries if the first one failed due + // to a potentially non-reproducible error. + #[async_std::test] + async fn test_execute_prepare_retry() { + let mut test = Builder::default().build(); + let mut host = test.host_handle(); + + // Submit a execute request that fails. + let (result_tx, _result_rx) = oneshot::channel(); + host.execute_pvf( + Pvf::from_discriminator(1), + TEST_EXECUTION_TIMEOUT, + b"pvf".to_vec(), + Priority::Critical, + result_tx, + ) + .await + .unwrap(); + + // The queue received the prepare request. + assert_matches!( + test.poll_and_recv_to_prepare_queue().await, + prepare::ToQueue::Enqueue { .. } + ); + // Send a PrepareError. + test.from_prepare_queue_tx + .send(prepare::FromQueue { + artifact_id: artifact_id(1), + result: Err(PrepareError::TimedOut), + }) + .await + .unwrap(); + + // Submit another execute request. + let (result_tx_2, _result_rx_2) = oneshot::channel(); + host.execute_pvf( + Pvf::from_discriminator(1), + TEST_EXECUTION_TIMEOUT, + b"pvf".to_vec(), + Priority::Critical, + result_tx_2, + ) + .await + .unwrap(); + + // Assert the prepare queue is empty. + test.poll_ensure_to_prepare_queue_is_empty().await; + + // Pause for enough time to reset the cooldown for this failed prepare request. + futures_timer::Delay::new(PREPARE_FAILURE_COOLDOWN).await; + + // Submit another execute request. + let (result_tx_3, _result_rx_3) = oneshot::channel(); + host.execute_pvf( + Pvf::from_discriminator(1), + TEST_EXECUTION_TIMEOUT, + b"pvf".to_vec(), + Priority::Critical, + result_tx_3, + ) + .await + .unwrap(); + + // Assert the prepare queue contains the request. + assert_matches!( + test.poll_and_recv_to_prepare_queue().await, + prepare::ToQueue::Enqueue { .. } + ); + } + + // Test that multiple execution requests don't trigger preparation retries if the first one + // failed due to reproducible error (e.g. Prevalidation). + #[async_std::test] + async fn test_execute_prepare_no_retry() { + let mut test = Builder::default().build(); + let mut host = test.host_handle(); + + // Submit a execute request that fails. + let (result_tx, _result_rx) = oneshot::channel(); + host.execute_pvf( + Pvf::from_discriminator(1), + TEST_EXECUTION_TIMEOUT, + b"pvf".to_vec(), + Priority::Critical, + result_tx, + ) + .await + .unwrap(); + + // The queue received the prepare request. + assert_matches!( + test.poll_and_recv_to_prepare_queue().await, + prepare::ToQueue::Enqueue { .. } + ); + // Send a PrepareError. + test.from_prepare_queue_tx + .send(prepare::FromQueue { + artifact_id: artifact_id(1), + result: Err(PrepareError::Prevalidation("reproducible error".into())), + }) + .await + .unwrap(); + + // Submit another execute request. + let (result_tx_2, _result_rx_2) = oneshot::channel(); + host.execute_pvf( + Pvf::from_discriminator(1), + TEST_EXECUTION_TIMEOUT, + b"pvf".to_vec(), + Priority::Critical, + result_tx_2, + ) + .await + .unwrap(); + + // Assert the prepare queue is empty. + test.poll_ensure_to_prepare_queue_is_empty().await; + + // Pause for enough time to reset the cooldown for this failed prepare request. + futures_timer::Delay::new(PREPARE_FAILURE_COOLDOWN).await; + + // Submit another execute request. + let (result_tx_3, _result_rx_3) = oneshot::channel(); + host.execute_pvf( + Pvf::from_discriminator(1), + TEST_EXECUTION_TIMEOUT, + b"pvf".to_vec(), + Priority::Critical, + result_tx_3, + ) + .await + .unwrap(); + + // Assert the prepare queue is empty - we do not retry for prevalidation errors. + test.poll_ensure_to_prepare_queue_is_empty().await; + } + + // Test that multiple heads-up requests trigger preparation retries if the first one failed. + #[async_std::test] + async fn test_heads_up_prepare_retry() { + let mut test = Builder::default().build(); + let mut host = test.host_handle(); + + // Submit a heads-up request that fails. + host.heads_up(vec![Pvf::from_discriminator(1)]).await.unwrap(); + + // The queue received the prepare request. + assert_matches!( + test.poll_and_recv_to_prepare_queue().await, + prepare::ToQueue::Enqueue { .. } + ); + // Send a PrepareError. + test.from_prepare_queue_tx + .send(prepare::FromQueue { + artifact_id: artifact_id(1), + result: Err(PrepareError::TimedOut), + }) + .await + .unwrap(); + + // Submit another heads-up request. + host.heads_up(vec![Pvf::from_discriminator(1)]).await.unwrap(); + + // Assert the prepare queue is empty. + test.poll_ensure_to_prepare_queue_is_empty().await; + + // Pause for enough time to reset the cooldown for this failed prepare request. + futures_timer::Delay::new(PREPARE_FAILURE_COOLDOWN).await; + + // Submit another heads-up request. + host.heads_up(vec![Pvf::from_discriminator(1)]).await.unwrap(); + + // Assert the prepare queue contains the request. + assert_matches!( + test.poll_and_recv_to_prepare_queue().await, + prepare::ToQueue::Enqueue { .. } + ); + } + #[async_std::test] async fn cancellation() { let mut test = Builder::default().build(); @@ -1187,7 +1524,10 @@ mod tests { ); test.from_prepare_queue_tx - .send(prepare::FromQueue { artifact_id: artifact_id(1), result: Ok(()) }) + .send(prepare::FromQueue { + artifact_id: artifact_id(1), + result: Ok(Duration::default()), + }) .await .unwrap(); diff --git a/node/core/pvf/src/lib.rs b/node/core/pvf/src/lib.rs index ef5f31889237..1aabb1100437 100644 --- a/node/core/pvf/src/lib.rs +++ b/node/core/pvf/src/lib.rs @@ -16,18 +16,27 @@ #![warn(missing_docs)] -//! A crate that implements PVF validation host. +//! A crate that implements the PVF validation host. +//! +//! For more background, refer to the Implementer's Guide: [PVF +//! Pre-checking](https://paritytech.github.io/polkadot/book/pvf-prechecking.html) and [Candidate +//! Validation](https://paritytech.github.io/polkadot/book/node/utility/candidate-validation.html#pvf-host). +//! +//! # Entrypoint //! //! This crate provides a simple API. You first [`start`] the validation host, which gives you the //! [handle][`ValidationHost`] and the future you need to poll. //! -//! Then using the handle the client can send two types of requests: +//! Then using the handle the client can send three types of requests: +//! +//! (a) PVF pre-checking. This takes the PVF [code][`Pvf`] and tries to prepare it (verify and +//! compile) in order to pre-check its validity. //! -//! (a) PVF execution. This accepts the PVF [`params`][`polkadot_parachain::primitives::ValidationParams`] +//! (b) PVF execution. This accepts the PVF [`params`][`polkadot_parachain::primitives::ValidationParams`] //! and the PVF [code][`Pvf`], prepares (verifies and compiles) the code, and then executes PVF //! with the `params`. //! -//! (b) Heads up. This request allows to signal that the given PVF may be needed soon and that it +//! (c) Heads up. This request allows to signal that the given PVF may be needed soon and that it //! should be prepared for execution. //! //! The preparation results are cached for some time after they either used or was signaled in heads up. @@ -39,7 +48,7 @@ //! PVF execution requests can specify the [priority][`Priority`] with which the given request should //! be handled. Different priority levels have different effects. This is discussed below. //! -//! Preparation started by a heads up signal always starts in with the background priority. If there +//! Preparation started by a heads up signal always starts with the background priority. If there //! is already a request for that PVF preparation under way the priority is inherited. If after heads //! up, a new PVF execution request comes in with a higher priority, then the original task's priority //! will be adjusted to match the new one if it's larger. @@ -48,6 +57,8 @@ //! //! # Under the hood //! +//! ## The flow +//! //! Under the hood, the validation host is built using a bunch of communicating processes, not //! dissimilar to actors. Each of such "processes" is a future task that contains an event loop that //! processes incoming messages, potentially delegating sub-tasks to other "processes". @@ -55,11 +66,13 @@ //! Two of these processes are queues. The first one is for preparation jobs and the second one is for //! execution. Both of the queues are backed by separate pools of workers of different kind. //! -//! Preparation workers handle preparation requests by preverifying and instrumenting PVF wasm code, +//! Preparation workers handle preparation requests by prevalidating and instrumenting PVF wasm code, //! and then passing it into the compiler, to prepare the artifact. //! -//! Artifact is a final product of preparation. If the preparation succeeded, then the artifact will -//! contain the compiled code usable for quick execution by a worker later on. +//! ## Artifacts +//! +//! An artifact is the final product of preparation. If the preparation succeeded, then the artifact +//! will contain the compiled code usable for quick execution by a worker later on. //! //! If the preparation failed, then the worker will still write the artifact with the error message. //! We save the artifact with the error so that we don't try to prepare the artifacts that are broken @@ -68,12 +81,14 @@ //! The artifact is saved on disk and is also tracked by an in memory table. This in memory table //! doesn't contain the artifact contents though, only a flag that the given artifact is compiled. //! +//! A pruning task will run at a fixed interval of time. This task will remove all artifacts that +//! weren't used or received a heads up signal for a while. +//! +//! ## Execution +//! //! The execute workers will be fed by the requests from the execution queue, which is basically a //! combination of a path to the compiled artifact and the //! [`params`][`polkadot_parachain::primitives::ValidationParams`]. -//! -//! Each fixed interval of time a pruning task will run. This task will remove all artifacts that -//! weren't used or received a heads up signal for a while. mod artifacts; mod error; diff --git a/node/core/pvf/src/metrics.rs b/node/core/pvf/src/metrics.rs index 547ee65f3e9d..8db105d895ea 100644 --- a/node/core/pvf/src/metrics.rs +++ b/node/core/pvf/src/metrics.rs @@ -155,8 +155,8 @@ impl metrics::Metrics for Metrics { "Time spent in preparing PVF artifacts in seconds", ) .buckets(vec![ - // This is synchronized with the PRECHECK_COMPILATION_TIMEOUT=60s - // and EXECUTE_COMPILATION_TIMEOUT=180s constants found in + // This is synchronized with the PRECHECK_PREPARATION_TIMEOUT=60s + // and LENIENT_PREPARATION_TIMEOUT=360s constants found in // src/prepare/worker.rs 0.1, 0.5, @@ -167,7 +167,10 @@ impl metrics::Metrics for Metrics { 20.0, 30.0, 60.0, - 180.0, + 120.0, + 240.0, + 360.0, + 480.0, ]), )?, registry, @@ -180,6 +183,9 @@ impl metrics::Metrics for Metrics { ).buckets(vec![ // This is synchronized with `APPROVAL_EXECUTION_TIMEOUT` and // `BACKING_EXECUTION_TIMEOUT` constants in `node/primitives/src/lib.rs` + 0.01, + 0.025, + 0.05, 0.1, 0.25, 0.5, @@ -189,6 +195,9 @@ impl metrics::Metrics for Metrics { 4.0, 5.0, 6.0, + 8.0, + 10.0, + 12.0, ]), )?, registry, diff --git a/node/core/pvf/src/prepare/pool.rs b/node/core/pvf/src/prepare/pool.rs index fad6ed167614..306588eb429a 100644 --- a/node/core/pvf/src/prepare/pool.rs +++ b/node/core/pvf/src/prepare/pool.rs @@ -65,7 +65,7 @@ pub enum ToPool { worker: Worker, code: Arc>, artifact_path: PathBuf, - compilation_timeout: Duration, + preparation_timeout: Duration, }, } @@ -210,7 +210,7 @@ fn handle_to_pool( metrics.prepare_worker().on_begin_spawn(); mux.push(spawn_worker_task(program_path.to_owned(), spawn_timeout).boxed()); }, - ToPool::StartWork { worker, code, artifact_path, compilation_timeout } => { + ToPool::StartWork { worker, code, artifact_path, preparation_timeout } => { if let Some(data) = spawned.get_mut(worker) { if let Some(idle) = data.idle.take() { let preparation_timer = metrics.time_preparation(); @@ -221,7 +221,7 @@ fn handle_to_pool( code, cache_path.to_owned(), artifact_path, - compilation_timeout, + preparation_timeout, preparation_timer, ) .boxed(), @@ -269,11 +269,11 @@ async fn start_work_task( code: Arc>, cache_path: PathBuf, artifact_path: PathBuf, - compilation_timeout: Duration, + preparation_timeout: Duration, _preparation_timer: Option, ) -> PoolEvent { let outcome = - worker::start_work(idle, code, &cache_path, artifact_path, compilation_timeout).await; + worker::start_work(idle, code, &cache_path, artifact_path, preparation_timeout).await; PoolEvent::StartWork(worker, outcome) } @@ -294,12 +294,15 @@ fn handle_mux( Ok(()) }, PoolEvent::StartWork(worker, outcome) => { + // If we receive any outcome other than `Concluded`, we attempt to kill the worker + // process. match outcome { Outcome::Concluded { worker: idle, result } => { let data = match spawned.get_mut(worker) { None => { // Perhaps the worker was killed meanwhile and the result is no longer - // relevant. + // relevant. We already send `Rip` when purging if we detect that the + // worker is dead. return Ok(()) }, Some(data) => data, diff --git a/node/core/pvf/src/prepare/queue.rs b/node/core/pvf/src/prepare/queue.rs index a77b88e00345..df0a8ec41883 100644 --- a/node/core/pvf/src/prepare/queue.rs +++ b/node/core/pvf/src/prepare/queue.rs @@ -33,7 +33,7 @@ pub enum ToQueue { /// /// Note that it is incorrect to enqueue the same PVF again without first receiving the /// [`FromQueue`] response. - Enqueue { priority: Priority, pvf: Pvf, compilation_timeout: Duration }, + Enqueue { priority: Priority, pvf: Pvf, preparation_timeout: Duration }, } /// A response from queue. @@ -80,7 +80,7 @@ struct JobData { priority: Priority, pvf: Pvf, /// The timeout for the preparation job. - compilation_timeout: Duration, + preparation_timeout: Duration, worker: Option, } @@ -208,8 +208,8 @@ impl Queue { async fn handle_to_queue(queue: &mut Queue, to_queue: ToQueue) -> Result<(), Fatal> { match to_queue { - ToQueue::Enqueue { priority, pvf, compilation_timeout } => { - handle_enqueue(queue, priority, pvf, compilation_timeout).await?; + ToQueue::Enqueue { priority, pvf, preparation_timeout } => { + handle_enqueue(queue, priority, pvf, preparation_timeout).await?; }, } Ok(()) @@ -219,13 +219,13 @@ async fn handle_enqueue( queue: &mut Queue, priority: Priority, pvf: Pvf, - compilation_timeout: Duration, + preparation_timeout: Duration, ) -> Result<(), Fatal> { gum::debug!( target: LOG_TARGET, validation_code_hash = ?pvf.code_hash, ?priority, - ?compilation_timeout, + ?preparation_timeout, "PVF is enqueued for preparation.", ); queue.metrics.prepare_enqueued(); @@ -247,7 +247,7 @@ async fn handle_enqueue( return Ok(()) } - let job = queue.jobs.insert(JobData { priority, pvf, compilation_timeout, worker: None }); + let job = queue.jobs.insert(JobData { priority, pvf, preparation_timeout, worker: None }); queue.artifact_id_to_job.insert(artifact_id, job); if let Some(available) = find_idle_worker(queue) { @@ -364,16 +364,14 @@ async fn handle_worker_concluded( // the pool up to the hard cap. spawn_extra_worker(queue, false).await?; } + } else if queue.limits.should_cull(queue.workers.len() + queue.spawn_inflight) { + // We no longer need services of this worker. Kill it. + queue.workers.remove(worker); + send_pool(&mut queue.to_pool_tx, pool::ToPool::Kill(worker)).await?; } else { - if queue.limits.should_cull(queue.workers.len() + queue.spawn_inflight) { - // We no longer need services of this worker. Kill it. - queue.workers.remove(worker); - send_pool(&mut queue.to_pool_tx, pool::ToPool::Kill(worker)).await?; - } else { - // see if there are more work available and schedule it. - if let Some(job) = queue.unscheduled.next() { - assign(queue, worker, job).await?; - } + // see if there are more work available and schedule it. + if let Some(job) = queue.unscheduled.next() { + assign(queue, worker, job).await?; } } @@ -439,7 +437,7 @@ async fn assign(queue: &mut Queue, worker: Worker, job: Job) -> Result<(), Fatal worker, code: job_data.pvf.code.clone(), artifact_path, - compilation_timeout: job_data.compilation_timeout, + preparation_timeout: job_data.preparation_timeout, }, ) .await?; @@ -494,7 +492,7 @@ pub fn start( #[cfg(test)] mod tests { use super::*; - use crate::{error::PrepareError, host::PRECHECK_COMPILATION_TIMEOUT}; + use crate::{error::PrepareError, host::PRECHECK_PREPARATION_TIMEOUT}; use assert_matches::assert_matches; use futures::{future::BoxFuture, FutureExt}; use slotmap::SlotMap; @@ -612,13 +610,17 @@ mod tests { test.send_queue(ToQueue::Enqueue { priority: Priority::Normal, pvf: pvf(1), - compilation_timeout: PRECHECK_COMPILATION_TIMEOUT, + preparation_timeout: PRECHECK_PREPARATION_TIMEOUT, }); assert_eq!(test.poll_and_recv_to_pool().await, pool::ToPool::Spawn); let w = test.workers.insert(()); test.send_from_pool(pool::FromPool::Spawned(w)); - test.send_from_pool(pool::FromPool::Concluded { worker: w, rip: false, result: Ok(()) }); + test.send_from_pool(pool::FromPool::Concluded { + worker: w, + rip: false, + result: Ok(Duration::default()), + }); assert_eq!(test.poll_and_recv_from_queue().await.artifact_id, pvf(1).as_artifact_id()); } @@ -626,12 +628,12 @@ mod tests { #[async_std::test] async fn dont_spawn_over_soft_limit_unless_critical() { let mut test = Test::new(2, 3); - let compilation_timeout = PRECHECK_COMPILATION_TIMEOUT; + let preparation_timeout = PRECHECK_PREPARATION_TIMEOUT; let priority = Priority::Normal; - test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(1), compilation_timeout }); - test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(2), compilation_timeout }); - test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(3), compilation_timeout }); + test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(1), preparation_timeout }); + test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(2), preparation_timeout }); + test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(3), preparation_timeout }); // Receive only two spawns. assert_eq!(test.poll_and_recv_to_pool().await, pool::ToPool::Spawn); @@ -647,7 +649,11 @@ mod tests { assert_matches!(test.poll_and_recv_to_pool().await, pool::ToPool::StartWork { .. }); assert_matches!(test.poll_and_recv_to_pool().await, pool::ToPool::StartWork { .. }); - test.send_from_pool(pool::FromPool::Concluded { worker: w1, rip: false, result: Ok(()) }); + test.send_from_pool(pool::FromPool::Concluded { + worker: w1, + rip: false, + result: Ok(Duration::default()), + }); assert_matches!(test.poll_and_recv_to_pool().await, pool::ToPool::StartWork { .. }); @@ -655,7 +661,7 @@ mod tests { test.send_queue(ToQueue::Enqueue { priority: Priority::Critical, pvf: pvf(4), - compilation_timeout, + preparation_timeout, }); // 2 out of 2 are working, but there is a critical job incoming. That means that spawning @@ -666,12 +672,12 @@ mod tests { #[async_std::test] async fn cull_unwanted() { let mut test = Test::new(1, 2); - let compilation_timeout = PRECHECK_COMPILATION_TIMEOUT; + let preparation_timeout = PRECHECK_PREPARATION_TIMEOUT; test.send_queue(ToQueue::Enqueue { priority: Priority::Normal, pvf: pvf(1), - compilation_timeout, + preparation_timeout, }); assert_eq!(test.poll_and_recv_to_pool().await, pool::ToPool::Spawn); let w1 = test.workers.insert(()); @@ -682,7 +688,7 @@ mod tests { test.send_queue(ToQueue::Enqueue { priority: Priority::Critical, pvf: pvf(2), - compilation_timeout, + preparation_timeout, }); assert_eq!(test.poll_and_recv_to_pool().await, pool::ToPool::Spawn); @@ -693,7 +699,11 @@ mod tests { // That's a bit silly in this context, but in production there will be an entire pool up // to the `soft_capacity` of workers and it doesn't matter which one to cull. Either way, // we just check that edge case of an edge case works. - test.send_from_pool(pool::FromPool::Concluded { worker: w1, rip: false, result: Ok(()) }); + test.send_from_pool(pool::FromPool::Concluded { + worker: w1, + rip: false, + result: Ok(Duration::default()), + }); assert_eq!(test.poll_and_recv_to_pool().await, pool::ToPool::Kill(w1)); } @@ -701,10 +711,10 @@ mod tests { async fn worker_mass_die_out_doesnt_stall_queue() { let mut test = Test::new(2, 2); - let (priority, compilation_timeout) = (Priority::Normal, PRECHECK_COMPILATION_TIMEOUT); - test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(1), compilation_timeout }); - test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(2), compilation_timeout }); - test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(3), compilation_timeout }); + let (priority, preparation_timeout) = (Priority::Normal, PRECHECK_PREPARATION_TIMEOUT); + test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(1), preparation_timeout }); + test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(2), preparation_timeout }); + test.send_queue(ToQueue::Enqueue { priority, pvf: pvf(3), preparation_timeout }); assert_eq!(test.poll_and_recv_to_pool().await, pool::ToPool::Spawn); assert_eq!(test.poll_and_recv_to_pool().await, pool::ToPool::Spawn); @@ -719,7 +729,11 @@ mod tests { assert_matches!(test.poll_and_recv_to_pool().await, pool::ToPool::StartWork { .. }); // Conclude worker 1 and rip it. - test.send_from_pool(pool::FromPool::Concluded { worker: w1, rip: true, result: Ok(()) }); + test.send_from_pool(pool::FromPool::Concluded { + worker: w1, + rip: true, + result: Ok(Duration::default()), + }); // Since there is still work, the queue requested one extra worker to spawn to handle the // remaining enqueued work items. @@ -734,7 +748,7 @@ mod tests { test.send_queue(ToQueue::Enqueue { priority: Priority::Normal, pvf: pvf(1), - compilation_timeout: PRECHECK_COMPILATION_TIMEOUT, + preparation_timeout: PRECHECK_PREPARATION_TIMEOUT, }); assert_eq!(test.poll_and_recv_to_pool().await, pool::ToPool::Spawn); @@ -759,7 +773,7 @@ mod tests { test.send_queue(ToQueue::Enqueue { priority: Priority::Normal, pvf: pvf(1), - compilation_timeout: PRECHECK_COMPILATION_TIMEOUT, + preparation_timeout: PRECHECK_PREPARATION_TIMEOUT, }); assert_eq!(test.poll_and_recv_to_pool().await, pool::ToPool::Spawn); diff --git a/node/core/pvf/src/prepare/worker.rs b/node/core/pvf/src/prepare/worker.rs index 77570b47360b..91361eacaf26 100644 --- a/node/core/pvf/src/prepare/worker.rs +++ b/node/core/pvf/src/prepare/worker.rs @@ -18,8 +18,9 @@ use crate::{ artifacts::CompiledArtifact, error::{PrepareError, PrepareResult}, worker_common::{ - bytes_to_path, framed_recv, framed_send, path_to_bytes, spawn_with_program_path, - tmpfile_in, worker_event_loop, IdleWorker, SpawnErr, WorkerHandle, + bytes_to_path, cpu_time_monitor_loop, framed_recv, framed_send, path_to_bytes, + spawn_with_program_path, tmpfile_in, worker_event_loop, IdleWorker, JobKind, SpawnErr, + WorkerHandle, JOB_TIMEOUT_WALL_CLOCK_FACTOR, }, LOG_TARGET, }; @@ -27,10 +28,20 @@ use async_std::{ io, os::unix::net::UnixStream, path::{Path, PathBuf}, + task, }; +use cpu_time::ProcessTime; use parity_scale_codec::{Decode, Encode}; use sp_core::hexdisplay::HexDisplay; -use std::{panic, sync::Arc, time::Duration}; +use std::{ + panic, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + thread, + time::Duration, +}; /// Spawns a new worker with the given program path that acts as the worker and the spawn timeout. /// @@ -58,14 +69,24 @@ pub enum Outcome { DidNotMakeIt, } +#[derive(Debug)] +enum Selected { + Done(PrepareResult), + IoErr, + Deadline, +} + /// Given the idle token of a worker and parameters of work, communicates with the worker and /// returns the outcome. +/// +/// NOTE: Returning the `TimedOut` or `DidNotMakeIt` errors will trigger the child process being +/// killed. pub async fn start_work( worker: IdleWorker, code: Arc>, cache_path: &Path, artifact_path: PathBuf, - compilation_timeout: Duration, + preparation_timeout: Duration, ) -> Outcome { let IdleWorker { mut stream, pid } = worker; @@ -77,7 +98,7 @@ pub async fn start_work( ); with_tmp_file(pid, cache_path, |tmp_file| async move { - if let Err(err) = send_request(&mut stream, code, &tmp_file).await { + if let Err(err) = send_request(&mut stream, code, &tmp_file, preparation_timeout).await { gum::warn!( target: LOG_TARGET, worker_pid = %pid, @@ -88,78 +109,53 @@ pub async fn start_work( } // Wait for the result from the worker, keeping in mind that there may be a timeout, the - // worker may get killed, or something along these lines. + // worker may get killed, or something along these lines. In that case we should propagate + // the error to the pool. // - // In that case we should propagate the error to the pool. - - #[derive(Debug)] - enum Selected { - Done(PrepareResult), - IoErr, - Deadline, - } + // We use a generous timeout here. This is in addition to the one in the child process, in + // case the child stalls. We have a wall clock timeout here in the host, but a CPU timeout + // in the child. We want to use CPU time because it varies less than wall clock time under + // load, but the CPU resources of the child can only be measured from the parent after the + // child process terminates. + let timeout = preparation_timeout * JOB_TIMEOUT_WALL_CLOCK_FACTOR; + let result = async_std::future::timeout(timeout, framed_recv(&mut stream)).await; - let selected = - match async_std::future::timeout(compilation_timeout, framed_recv(&mut stream)).await { - Ok(Ok(response_bytes)) => { - // Received bytes from worker within the time limit. - // By convention we expect encoded `PrepareResult`. - if let Ok(result) = PrepareResult::decode(&mut response_bytes.as_slice()) { - if result.is_ok() { - gum::debug!( - target: LOG_TARGET, - worker_pid = %pid, - "promoting WIP artifact {} to {}", - tmp_file.display(), - artifact_path.display(), - ); - - async_std::fs::rename(&tmp_file, &artifact_path) - .await - .map(|_| Selected::Done(result)) - .unwrap_or_else(|err| { - gum::warn!( - target: LOG_TARGET, - worker_pid = %pid, - "failed to rename the artifact from {} to {}: {:?}", - tmp_file.display(), - artifact_path.display(), - err, - ); - Selected::IoErr - }) - } else { - Selected::Done(result) - } - } else { - // We received invalid bytes from the worker. - let bound_bytes = &response_bytes[..response_bytes.len().min(4)]; - gum::warn!( - target: LOG_TARGET, - worker_pid = %pid, - "received unexpected response from the prepare worker: {}", - HexDisplay::from(&bound_bytes), - ); - Selected::IoErr - } - }, - Ok(Err(err)) => { - // Communication error within the time limit. - gum::warn!( - target: LOG_TARGET, - worker_pid = %pid, - "failed to recv a prepare response: {:?}", - err, - ); - Selected::IoErr - }, - Err(_) => { - // Timed out. - Selected::Deadline - }, - }; + let selected = match result { + // Received bytes from worker within the time limit. + Ok(Ok(response_bytes)) => + handle_response_bytes( + response_bytes, + pid, + tmp_file, + artifact_path, + preparation_timeout, + ) + .await, + Ok(Err(err)) => { + // Communication error within the time limit. + gum::warn!( + target: LOG_TARGET, + worker_pid = %pid, + "failed to recv a prepare response: {:?}", + err, + ); + Selected::IoErr + }, + Err(_) => { + // Timed out here on the host. + gum::warn!( + target: LOG_TARGET, + worker_pid = %pid, + "did not recv a prepare response within the time limit", + ); + Selected::Deadline + }, + }; + // NOTE: A `TimedOut` or `DidNotMakeIt` error triggers the child process being killed. match selected { + // Timed out on the child. This should already be logged by the child. + Selected::Done(Err(PrepareError::TimedOut)) => Outcome::TimedOut, Selected::Done(result) => Outcome::Concluded { worker: IdleWorker { stream, pid }, result }, Selected::Deadline => Outcome::TimedOut, @@ -169,6 +165,76 @@ pub async fn start_work( .await } +/// Handles the case where we successfully received response bytes on the host from the child. +/// +/// NOTE: Here we know the artifact exists, but is still located in a temporary file which will be +/// cleared by `with_tmp_file`. +async fn handle_response_bytes( + response_bytes: Vec, + pid: u32, + tmp_file: PathBuf, + artifact_path: PathBuf, + preparation_timeout: Duration, +) -> Selected { + // By convention we expect encoded `PrepareResult`. + let result = match PrepareResult::decode(&mut response_bytes.as_slice()) { + Ok(result) => result, + Err(_) => { + // We received invalid bytes from the worker. + let bound_bytes = &response_bytes[..response_bytes.len().min(4)]; + gum::warn!( + target: LOG_TARGET, + worker_pid = %pid, + "received unexpected response from the prepare worker: {}", + HexDisplay::from(&bound_bytes), + ); + return Selected::IoErr + }, + }; + let cpu_time_elapsed = match result { + Ok(result) => result, + Err(_) => return Selected::Done(result), + }; + + if cpu_time_elapsed > preparation_timeout { + // The job didn't complete within the timeout. + gum::warn!( + target: LOG_TARGET, + worker_pid = %pid, + "prepare job took {}ms cpu time, exceeded preparation timeout {}ms. Clearing WIP artifact {}", + cpu_time_elapsed.as_millis(), + preparation_timeout.as_millis(), + tmp_file.display(), + ); + + // Return a timeout error. + return Selected::Deadline + } + + gum::debug!( + target: LOG_TARGET, + worker_pid = %pid, + "promoting WIP artifact {} to {}", + tmp_file.display(), + artifact_path.display(), + ); + + async_std::fs::rename(&tmp_file, &artifact_path) + .await + .map(|_| Selected::Done(result)) + .unwrap_or_else(|err| { + gum::warn!( + target: LOG_TARGET, + worker_pid = %pid, + "failed to rename the artifact from {} to {}: {:?}", + tmp_file.display(), + artifact_path.display(), + err, + ); + Selected::IoErr + }) +} + /// Create a temporary file for an artifact at the given cache path and execute the given /// future/closure passing the file path in. /// @@ -218,13 +284,15 @@ async fn send_request( stream: &mut UnixStream, code: Arc>, tmp_file: &Path, + preparation_timeout: Duration, ) -> io::Result<()> { - framed_send(stream, &*code).await?; + framed_send(stream, &code).await?; framed_send(stream, path_to_bytes(tmp_file)).await?; + framed_send(stream, &preparation_timeout.encode()).await?; Ok(()) } -async fn recv_request(stream: &mut UnixStream) -> io::Result<(Vec, PathBuf)> { +async fn recv_request(stream: &mut UnixStream) -> io::Result<(Vec, PathBuf, Duration)> { let code = framed_recv(stream).await?; let tmp_file = framed_recv(stream).await?; let tmp_file = bytes_to_path(&tmp_file).ok_or_else(|| { @@ -233,7 +301,14 @@ async fn recv_request(stream: &mut UnixStream) -> io::Result<(Vec, PathBuf)> "prepare pvf recv_request: non utf-8 artifact path".to_string(), ) })?; - Ok((code, tmp_file)) + let preparation_timeout = framed_recv(stream).await?; + let preparation_timeout = Duration::decode(&mut &preparation_timeout[..]).map_err(|_| { + io::Error::new( + io::ErrorKind::Other, + "prepare pvf recv_request: failed to decode duration".to_string(), + ) + })?; + Ok((code, tmp_file, preparation_timeout)) } /// The entrypoint that the spawned prepare worker should start with. The `socket_path` specifies @@ -241,7 +316,7 @@ async fn recv_request(stream: &mut UnixStream) -> io::Result<(Vec, PathBuf)> pub fn worker_entrypoint(socket_path: &str) { worker_event_loop("prepare", socket_path, |mut stream| async move { loop { - let (code, dest) = recv_request(&mut stream).await?; + let (code, dest, preparation_timeout) = recv_request(&mut stream).await?; gum::debug!( target: LOG_TARGET, @@ -249,18 +324,54 @@ pub fn worker_entrypoint(socket_path: &str) { "worker: preparing artifact", ); - let result = match prepare_artifact(&code) { + // Create a lock flag. We set it when either thread finishes. + let lock = Arc::new(AtomicBool::new(false)); + let cpu_time_start = ProcessTime::now(); + + // Spawn a new thread that runs the CPU time monitor. Continuously wakes up from + // sleeping and then either sleeps for the remaining CPU time, or kills the process if + // we exceed the CPU timeout. + let (stream_2, cpu_time_start_2, preparation_timeout_2, lock_2) = + (stream.clone(), cpu_time_start, preparation_timeout, lock.clone()); + let handle = + thread::Builder::new().name("CPU time monitor".into()).spawn(move || { + task::block_on(async { + cpu_time_monitor_loop( + JobKind::Prepare, + stream_2, + cpu_time_start_2, + preparation_timeout_2, + lock_2, + ) + .await; + }) + })?; + + // Prepares the artifact in a separate thread. + let result = match prepare_artifact(&code).await { Err(err) => { // Serialized error will be written into the socket. Err(err) }, Ok(compiled_artifact) => { + let cpu_time_elapsed = cpu_time_start.elapsed(); + + let lock_result = + lock.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed); + if lock_result.is_err() { + // The other thread is still sending an error response over the socket. Wait on it and + // return. + let _ = handle.join(); + // Monitor thread detected timeout and likely already terminated the + // process, nothing to do. + continue + } + // Write the serialized artifact into a temp file. - // PVF host only keeps artifacts statuses in its memory, - // successfully compiled code gets stored on the disk (and - // consequently deserialized by execute-workers). The prepare - // worker is only required to send an empty `Ok` to the pool - // to indicate the success. + // + // PVF host only keeps artifacts statuses in its memory, successfully compiled code gets stored + // on the disk (and consequently deserialized by execute-workers). The prepare worker is only + // required to send `Ok` to the pool to indicate the success. gum::debug!( target: LOG_TARGET, @@ -270,7 +381,7 @@ pub fn worker_entrypoint(socket_path: &str) { ); async_std::fs::write(&dest, &compiled_artifact).await?; - Ok(()) + Ok(cpu_time_elapsed) }, }; @@ -279,7 +390,7 @@ pub fn worker_entrypoint(socket_path: &str) { }); } -fn prepare_artifact(code: &[u8]) -> Result { +async fn prepare_artifact(code: &[u8]) -> Result { panic::catch_unwind(|| { let blob = match crate::executor_intf::prevalidate(code) { Err(err) => return Err(PrepareError::Prevalidation(format!("{:?}", err))), diff --git a/node/core/pvf/src/priority.rs b/node/core/pvf/src/priority.rs index de169be0696b..b80c9195832a 100644 --- a/node/core/pvf/src/priority.rs +++ b/node/core/pvf/src/priority.rs @@ -24,7 +24,7 @@ pub enum Priority { Normal, /// This priority is used for requests that are required to be processed as soon as possible. /// - /// For example, backing is on critical path and require execution as soon as possible. + /// For example, backing is on a critical path and requires execution as soon as possible. Critical, } diff --git a/node/core/pvf/src/pvf.rs b/node/core/pvf/src/pvf.rs index 901cc1c70d6e..d06968a13d43 100644 --- a/node/core/pvf/src/pvf.rs +++ b/node/core/pvf/src/pvf.rs @@ -19,7 +19,7 @@ use polkadot_parachain::primitives::ValidationCodeHash; use sp_core::blake2_256; use std::{fmt, sync::Arc}; -/// A struct that carries code of a parachain validation function and it's hash. +/// A struct that carries code of a parachain validation function and its hash. /// /// Should be cheap to clone. #[derive(Clone)] diff --git a/node/core/pvf/src/testing.rs b/node/core/pvf/src/testing.rs index 3b64d130fc6a..cbd37b06d403 100644 --- a/node/core/pvf/src/testing.rs +++ b/node/core/pvf/src/testing.rs @@ -34,7 +34,7 @@ pub fn validate_candidate( let code = sp_maybe_compressed_blob::decompress(code, 10 * 1024 * 1024) .expect("Decompressing code failed"); - let blob = prevalidate(&*code)?; + let blob = prevalidate(&code)?; let artifact = prepare(blob)?; let tmpdir = tempfile::tempdir()?; let artifact_path = tmpdir.path().join("blob"); diff --git a/node/core/pvf/src/worker_common.rs b/node/core/pvf/src/worker_common.rs index 8614b07d8166..f9eaf42dcf67 100644 --- a/node/core/pvf/src/worker_common.rs +++ b/node/core/pvf/src/worker_common.rs @@ -16,25 +16,54 @@ //! Common logic for implementation of worker processes. -use crate::LOG_TARGET; +use crate::{execute::ExecuteResponse, PrepareError, LOG_TARGET}; use async_std::{ io, os::unix::net::{UnixListener, UnixStream}, path::{Path, PathBuf}, }; +use cpu_time::ProcessTime; use futures::{ never::Never, AsyncRead, AsyncReadExt as _, AsyncWrite, AsyncWriteExt as _, FutureExt as _, }; use futures_timer::Delay; +use parity_scale_codec::Encode; use pin_project::pin_project; use rand::Rng; use std::{ fmt, mem, pin::Pin, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, task::{Context, Poll}, time::Duration, }; +/// A multiple of the job timeout (in CPU time) for which we are willing to wait on the host (in +/// wall clock time). This is lenient because CPU time may go slower than wall clock time. +pub const JOB_TIMEOUT_WALL_CLOCK_FACTOR: u32 = 4; + +/// Some allowed overhead that we account for in the "CPU time monitor" thread's sleeps, on the +/// child process. +pub const JOB_TIMEOUT_OVERHEAD: Duration = Duration::from_millis(50); + +#[derive(Copy, Clone, Debug)] +pub enum JobKind { + Prepare, + Execute, +} + +impl fmt::Display for JobKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Prepare => write!(f, "prepare"), + Self::Execute => write!(f, "execute"), + } + } +} + /// This is publicly exposed only for integration tests. #[doc(hidden)] pub async fn spawn_with_program_path( @@ -169,6 +198,75 @@ where ); } +/// Loop that runs in the CPU time monitor thread on prepare and execute jobs. Continuously wakes up +/// from sleeping and then either sleeps for the remaining CPU time, or sends back a timeout error +/// if we exceed the CPU timeout. +/// +/// NOTE: If the job completes and this thread is still sleeping, it will continue sleeping in the +/// background. When it wakes, it will see that the flag has been set and return. +pub async fn cpu_time_monitor_loop( + job_kind: JobKind, + mut stream: UnixStream, + cpu_time_start: ProcessTime, + timeout: Duration, + lock: Arc, +) { + loop { + let cpu_time_elapsed = cpu_time_start.elapsed(); + + // Treat the timeout as CPU time, which is less subject to variance due to load. + if cpu_time_elapsed > timeout { + let result = lock.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed); + if result.is_err() { + // Hit the job-completed case first, return from this thread. + return + } + + // Log if we exceed the timeout. + gum::warn!( + target: LOG_TARGET, + worker_pid = %std::process::id(), + "{job_kind} job took {}ms cpu time, exceeded {job_kind} timeout {}ms", + cpu_time_elapsed.as_millis(), + timeout.as_millis(), + ); + + // Send back a `TimedOut` error. + // + // NOTE: This will cause the worker, whether preparation or execution, to be killed by + // the host. We do not kill the process here because it would interfere with the proper + // handling of this error. + let encoded_result = match job_kind { + JobKind::Prepare => { + let result: Result<(), PrepareError> = Err(PrepareError::TimedOut); + result.encode() + }, + JobKind::Execute => { + let result = ExecuteResponse::TimedOut; + result.encode() + }, + }; + // If we error here there is nothing we can do apart from log it. The receiving side + // will just have to time out. + if let Err(err) = framed_send(&mut stream, encoded_result.as_slice()).await { + gum::warn!( + target: LOG_TARGET, + worker_pid = %std::process::id(), + "{job_kind} worker -> pvf host: error sending result over the socket: {:?}", + err + ); + } + + return + } + + // Sleep for the remaining CPU time, plus a bit to account for overhead. Note that the sleep + // is wall clock time. The CPU clock may be slower than the wall clock. + let sleep_interval = timeout - cpu_time_elapsed + JOB_TIMEOUT_OVERHEAD; + std::thread::sleep(sleep_interval); + } +} + /// A struct that represents an idle worker. /// /// This struct is supposed to be used as a token that is passed by move into a subroutine that @@ -200,8 +298,8 @@ pub enum SpawnErr { /// This is a representation of a potentially running worker. Drop it and the process will be killed. /// /// A worker's handle is also a future that resolves when it's detected that the worker's process -/// has been terminated. Since the worker is running in another process it is obviously not necessarily -/// to poll this future to make the worker run, it's only for termination detection. +/// has been terminated. Since the worker is running in another process it is obviously not +/// necessary to poll this future to make the worker run, it's only for termination detection. /// /// This future relies on the fact that a child process's stdout `fd` is closed upon it's termination. #[pin_project] @@ -209,6 +307,7 @@ pub struct WorkerHandle { child: async_process::Child, #[pin] stdout: async_process::ChildStdout, + program: PathBuf, drop_box: Box<[u8]>, } @@ -233,6 +332,7 @@ impl WorkerHandle { Ok(WorkerHandle { child, stdout, + program: program.as_ref().to_path_buf(), // We don't expect the bytes to be ever read. But in case we do, we should not use a buffer // of a small size, because otherwise if the child process does return any data we will end up // issuing a syscall for each byte. We also prefer not to do allocate that on the stack, since @@ -267,9 +367,19 @@ impl futures::Future for WorkerHandle { cx.waker().wake_by_ref(); Poll::Pending }, - Err(_) => { + Err(err) => { // The implementation is guaranteed to not to return `WouldBlock` and Interrupted. This - // leaves us with a legit errors which we suppose were due to termination. + // leaves us with legit errors which we suppose were due to termination. + + // Log the status code. + gum::debug!( + target: LOG_TARGET, + worker_pid = %me.child.id(), + status_code = ?me.child.try_status(), + "pvf worker ({}): {:?}", + me.program.display(), + err, + ); Poll::Ready(()) }, } diff --git a/node/core/pvf/tests/it/adder.rs b/node/core/pvf/tests/it/adder.rs index 83cbd27b6ed5..69b6b7d21979 100644 --- a/node/core/pvf/tests/it/adder.rs +++ b/node/core/pvf/tests/it/adder.rs @@ -23,7 +23,7 @@ use polkadot_parachain::primitives::{ }; #[async_std::test] -async fn execute_good_on_parent() { +async fn execute_good_block_on_parent() { let parent_head = HeadData { number: 0, parent_hash: [0; 32], post_state: hash_state(0) }; let block_data = BlockData { state: 0, add: 512 }; @@ -89,7 +89,7 @@ async fn execute_good_chain_on_parent() { } #[async_std::test] -async fn execute_bad_on_parent() { +async fn execute_bad_block_on_parent() { let parent_head = HeadData { number: 0, parent_hash: [0; 32], post_state: hash_state(0) }; let block_data = BlockData { diff --git a/node/core/pvf/tests/it/main.rs b/node/core/pvf/tests/it/main.rs index bf0983d50874..a6aaf5d369d4 100644 --- a/node/core/pvf/tests/it/main.rs +++ b/node/core/pvf/tests/it/main.rs @@ -101,6 +101,7 @@ async fn terminates_on_timeout() { #[async_std::test] async fn parallel_execution() { + // Run some jobs that do not complete, thus timing out. let host = TestHost::new(); let execute_pvf_future_1 = host.validate_candidate( halt::wasm_binary_unwrap(), @@ -124,11 +125,14 @@ async fn parallel_execution() { let start = std::time::Instant::now(); let (_, _) = futures::join!(execute_pvf_future_1, execute_pvf_future_2); - // total time should be < 2 x EXECUTION_TIMEOUT_SEC - const EXECUTION_TIMEOUT_SEC: u64 = 3; + // Total time should be < 2 x TEST_EXECUTION_TIMEOUT (two workers run in parallel). + let duration = std::time::Instant::now().duration_since(start); + let max_duration = 2 * TEST_EXECUTION_TIMEOUT; assert!( - std::time::Instant::now().duration_since(start) < - std::time::Duration::from_secs(EXECUTION_TIMEOUT_SEC * 2) + duration < max_duration, + "Expected duration {}ms to be less than {}ms", + duration.as_millis(), + max_duration.as_millis() ); } @@ -141,6 +145,7 @@ async fn execute_queue_doesnt_stall_if_workers_died() { // Here we spawn 8 validation jobs for the `halt` PVF and share those between 5 workers. The // first five jobs should timeout and the workers killed. For the next 3 jobs a new batch of // workers should be spun up. + let start = std::time::Instant::now(); futures::future::join_all((0u8..=8).map(|_| { host.validate_candidate( halt::wasm_binary_unwrap(), @@ -153,4 +158,15 @@ async fn execute_queue_doesnt_stall_if_workers_died() { ) })) .await; + + // Total time should be >= 2 x TEST_EXECUTION_TIMEOUT (two separate sets of workers that should + // both timeout). + let duration = std::time::Instant::now().duration_since(start); + let max_duration = 2 * TEST_EXECUTION_TIMEOUT; + assert!( + duration >= max_duration, + "Expected duration {}ms to be greater than or equal to {}ms", + duration.as_millis(), + max_duration.as_millis() + ); } diff --git a/node/core/runtime-api/Cargo.toml b/node/core/runtime-api/Cargo.toml index 232d7741bc81..569e36a10950 100644 --- a/node/core/runtime-api/Cargo.toml +++ b/node/core/runtime-api/Cargo.toml @@ -1,16 +1,15 @@ [package] name = "polkadot-node-core-runtime-api" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" gum = { package = "tracing-gum", path = "../../gum" } -memory-lru = "0.1.1" -parity-util-mem = { version = "0.12.0", default-features = false } +lru = "0.8" -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-primitives = { path = "../../../primitives" } polkadot-node-subsystem = { path = "../../subsystem" } @@ -18,10 +17,10 @@ polkadot-node-subsystem-types = { path = "../../subsystem-types" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } [dev-dependencies] -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures = { version = "0.3.21", features = ["thread-pool"] } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } polkadot-node-primitives = { path = "../../primitives" } diff --git a/node/core/runtime-api/src/cache.rs b/node/core/runtime-api/src/cache.rs index 0fe9b74dc86d..d202b46d0da3 100644 --- a/node/core/runtime-api/src/cache.rs +++ b/node/core/runtime-api/src/cache.rs @@ -14,10 +14,9 @@ // 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, num::NonZeroUsize}; -use memory_lru::{MemoryLruCache, ResidentSize}; -use parity_util_mem::{MallocSizeOf, MallocSizeOfExt}; +use lru::LruCache; use sp_consensus_babe::Epoch; use polkadot_primitives::v2::{ @@ -28,126 +27,67 @@ use polkadot_primitives::v2::{ ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, }; -const AUTHORITIES_CACHE_SIZE: usize = 128 * 1024; -const VALIDATORS_CACHE_SIZE: usize = 64 * 1024; -const VALIDATOR_GROUPS_CACHE_SIZE: usize = 64 * 1024; -const AVAILABILITY_CORES_CACHE_SIZE: usize = 64 * 1024; -const PERSISTED_VALIDATION_DATA_CACHE_SIZE: usize = 64 * 1024; -const ASSUMED_VALIDATION_DATA_CACHE_SIZE: usize = 64 * 1024; -const CHECK_VALIDATION_OUTPUTS_CACHE_SIZE: usize = 64 * 1024; -const SESSION_INDEX_FOR_CHILD_CACHE_SIZE: usize = 64 * 1024; -const VALIDATION_CODE_CACHE_SIZE: usize = 10 * 1024 * 1024; -const CANDIDATE_PENDING_AVAILABILITY_CACHE_SIZE: usize = 64 * 1024; -const CANDIDATE_EVENTS_CACHE_SIZE: usize = 64 * 1024; -const SESSION_INFO_CACHE_SIZE: usize = 64 * 1024; -const DMQ_CONTENTS_CACHE_SIZE: usize = 64 * 1024; -const INBOUND_HRMP_CHANNELS_CACHE_SIZE: usize = 64 * 1024; -const CURRENT_BABE_EPOCH_CACHE_SIZE: usize = 64 * 1024; -const ON_CHAIN_VOTES_CACHE_SIZE: usize = 3 * 1024; -const PVFS_REQUIRE_PRECHECK_SIZE: usize = 1024; -const VALIDATION_CODE_HASH_CACHE_SIZE: usize = 64 * 1024; -const VERSION_CACHE_SIZE: usize = 4 * 1024; -const DISPUTES_CACHE_SIZE: usize = 64 * 1024; - -struct ResidentSizeOf(T); - -impl ResidentSize for ResidentSizeOf { - fn resident_size(&self) -> usize { - std::mem::size_of::() + self.0.malloc_size_of() - } -} - -struct DoesNotAllocate(T); - -impl ResidentSize for DoesNotAllocate { - fn resident_size(&self) -> usize { - std::mem::size_of::() - } -} - -// this is an ugly workaround for `AuthorityDiscoveryId` -// not implementing `MallocSizeOf` -struct VecOfDoesNotAllocate(Vec); - -impl ResidentSize for VecOfDoesNotAllocate { - fn resident_size(&self) -> usize { - std::mem::size_of::() * self.0.capacity() - } -} +/// For consistency we have the same capacity for all caches. We use 128 as we'll only need that +/// much if finality stalls (we only query state for unfinalized blocks + maybe latest finalized). +/// In any case, a cache is an optimization. We should avoid a situation where having a large cache +/// leads to OOM or puts pressure on other important stuff like PVF execution/preparation. +const DEFAULT_CACHE_CAP: NonZeroUsize = match NonZeroUsize::new(128) { + Some(cap) => cap, + None => panic!("lru capacity must be non-zero"), +}; pub(crate) struct RequestResultCache { - authorities: MemoryLruCache>, - validators: MemoryLruCache>>, - validator_groups: - MemoryLruCache>, GroupRotationInfo)>>, - availability_cores: MemoryLruCache>>, - persisted_validation_data: MemoryLruCache< - (Hash, ParaId, OccupiedCoreAssumption), - ResidentSizeOf>, - >, - assumed_validation_data: MemoryLruCache< - (ParaId, Hash), - ResidentSizeOf>, - >, - check_validation_outputs: - MemoryLruCache<(Hash, ParaId, CandidateCommitments), ResidentSizeOf>, - session_index_for_child: MemoryLruCache>, - validation_code: MemoryLruCache< - (Hash, ParaId, OccupiedCoreAssumption), - ResidentSizeOf>, - >, - validation_code_by_hash: - MemoryLruCache>>, - candidate_pending_availability: - MemoryLruCache<(Hash, ParaId), ResidentSizeOf>>, - candidate_events: MemoryLruCache>>, - session_info: MemoryLruCache>, - dmq_contents: - MemoryLruCache<(Hash, ParaId), ResidentSizeOf>>>, - inbound_hrmp_channels_contents: MemoryLruCache< - (Hash, ParaId), - ResidentSizeOf>>>, - >, - current_babe_epoch: MemoryLruCache>, - on_chain_votes: MemoryLruCache>>, - pvfs_require_precheck: MemoryLruCache>>, - validation_code_hash: MemoryLruCache< - (Hash, ParaId, OccupiedCoreAssumption), - ResidentSizeOf>, - >, - version: MemoryLruCache>, - disputes: MemoryLruCache< - Hash, - ResidentSizeOf)>>, - >, + authorities: LruCache>, + validators: LruCache>, + validator_groups: LruCache>, GroupRotationInfo)>, + availability_cores: LruCache>, + persisted_validation_data: + LruCache<(Hash, ParaId, OccupiedCoreAssumption), Option>, + assumed_validation_data: + LruCache<(ParaId, Hash), Option<(PersistedValidationData, ValidationCodeHash)>>, + check_validation_outputs: LruCache<(Hash, ParaId, CandidateCommitments), bool>, + session_index_for_child: LruCache, + validation_code: LruCache<(Hash, ParaId, OccupiedCoreAssumption), Option>, + validation_code_by_hash: LruCache>, + candidate_pending_availability: LruCache<(Hash, ParaId), Option>, + candidate_events: LruCache>, + session_info: LruCache, + dmq_contents: LruCache<(Hash, ParaId), Vec>>, + inbound_hrmp_channels_contents: + LruCache<(Hash, ParaId), BTreeMap>>>, + current_babe_epoch: LruCache, + on_chain_votes: LruCache>, + pvfs_require_precheck: LruCache>, + validation_code_hash: + LruCache<(Hash, ParaId, OccupiedCoreAssumption), Option>, + version: LruCache, + disputes: LruCache)>>, } impl Default for RequestResultCache { fn default() -> Self { Self { - authorities: MemoryLruCache::new(AUTHORITIES_CACHE_SIZE), - validators: MemoryLruCache::new(VALIDATORS_CACHE_SIZE), - validator_groups: MemoryLruCache::new(VALIDATOR_GROUPS_CACHE_SIZE), - availability_cores: MemoryLruCache::new(AVAILABILITY_CORES_CACHE_SIZE), - persisted_validation_data: MemoryLruCache::new(PERSISTED_VALIDATION_DATA_CACHE_SIZE), - assumed_validation_data: MemoryLruCache::new(ASSUMED_VALIDATION_DATA_CACHE_SIZE), - check_validation_outputs: MemoryLruCache::new(CHECK_VALIDATION_OUTPUTS_CACHE_SIZE), - session_index_for_child: MemoryLruCache::new(SESSION_INDEX_FOR_CHILD_CACHE_SIZE), - validation_code: MemoryLruCache::new(VALIDATION_CODE_CACHE_SIZE), - validation_code_by_hash: MemoryLruCache::new(VALIDATION_CODE_CACHE_SIZE), - candidate_pending_availability: MemoryLruCache::new( - CANDIDATE_PENDING_AVAILABILITY_CACHE_SIZE, - ), - candidate_events: MemoryLruCache::new(CANDIDATE_EVENTS_CACHE_SIZE), - session_info: MemoryLruCache::new(SESSION_INFO_CACHE_SIZE), - dmq_contents: MemoryLruCache::new(DMQ_CONTENTS_CACHE_SIZE), - inbound_hrmp_channels_contents: MemoryLruCache::new(INBOUND_HRMP_CHANNELS_CACHE_SIZE), - current_babe_epoch: MemoryLruCache::new(CURRENT_BABE_EPOCH_CACHE_SIZE), - on_chain_votes: MemoryLruCache::new(ON_CHAIN_VOTES_CACHE_SIZE), - pvfs_require_precheck: MemoryLruCache::new(PVFS_REQUIRE_PRECHECK_SIZE), - validation_code_hash: MemoryLruCache::new(VALIDATION_CODE_HASH_CACHE_SIZE), - version: MemoryLruCache::new(VERSION_CACHE_SIZE), - disputes: MemoryLruCache::new(DISPUTES_CACHE_SIZE), + authorities: LruCache::new(DEFAULT_CACHE_CAP), + validators: LruCache::new(DEFAULT_CACHE_CAP), + validator_groups: LruCache::new(DEFAULT_CACHE_CAP), + availability_cores: LruCache::new(DEFAULT_CACHE_CAP), + persisted_validation_data: LruCache::new(DEFAULT_CACHE_CAP), + assumed_validation_data: LruCache::new(DEFAULT_CACHE_CAP), + check_validation_outputs: LruCache::new(DEFAULT_CACHE_CAP), + session_index_for_child: LruCache::new(DEFAULT_CACHE_CAP), + validation_code: LruCache::new(DEFAULT_CACHE_CAP), + validation_code_by_hash: LruCache::new(DEFAULT_CACHE_CAP), + candidate_pending_availability: LruCache::new(DEFAULT_CACHE_CAP), + candidate_events: LruCache::new(DEFAULT_CACHE_CAP), + session_info: LruCache::new(DEFAULT_CACHE_CAP), + dmq_contents: LruCache::new(DEFAULT_CACHE_CAP), + inbound_hrmp_channels_contents: LruCache::new(DEFAULT_CACHE_CAP), + current_babe_epoch: LruCache::new(DEFAULT_CACHE_CAP), + on_chain_votes: LruCache::new(DEFAULT_CACHE_CAP), + pvfs_require_precheck: LruCache::new(DEFAULT_CACHE_CAP), + validation_code_hash: LruCache::new(DEFAULT_CACHE_CAP), + version: LruCache::new(DEFAULT_CACHE_CAP), + disputes: LruCache::new(DEFAULT_CACHE_CAP), } } } @@ -157,7 +97,7 @@ impl RequestResultCache { &mut self, relay_parent: &Hash, ) -> Option<&Vec> { - self.authorities.get(relay_parent).map(|v| &v.0) + self.authorities.get(relay_parent) } pub(crate) fn cache_authorities( @@ -165,22 +105,22 @@ impl RequestResultCache { relay_parent: Hash, authorities: Vec, ) { - self.authorities.insert(relay_parent, VecOfDoesNotAllocate(authorities)); + self.authorities.put(relay_parent, authorities); } pub(crate) fn validators(&mut self, relay_parent: &Hash) -> Option<&Vec> { - self.validators.get(relay_parent).map(|v| &v.0) + self.validators.get(relay_parent) } pub(crate) fn cache_validators(&mut self, relay_parent: Hash, validators: Vec) { - self.validators.insert(relay_parent, ResidentSizeOf(validators)); + self.validators.put(relay_parent, validators); } pub(crate) fn validator_groups( &mut self, relay_parent: &Hash, ) -> Option<&(Vec>, GroupRotationInfo)> { - self.validator_groups.get(relay_parent).map(|v| &v.0) + self.validator_groups.get(relay_parent) } pub(crate) fn cache_validator_groups( @@ -188,22 +128,22 @@ impl RequestResultCache { relay_parent: Hash, groups: (Vec>, GroupRotationInfo), ) { - self.validator_groups.insert(relay_parent, ResidentSizeOf(groups)); + self.validator_groups.put(relay_parent, groups); } pub(crate) fn availability_cores(&mut self, relay_parent: &Hash) -> Option<&Vec> { - self.availability_cores.get(relay_parent).map(|v| &v.0) + self.availability_cores.get(relay_parent) } pub(crate) fn cache_availability_cores(&mut self, relay_parent: Hash, cores: Vec) { - self.availability_cores.insert(relay_parent, ResidentSizeOf(cores)); + self.availability_cores.put(relay_parent, cores); } pub(crate) fn persisted_validation_data( &mut self, key: (Hash, ParaId, OccupiedCoreAssumption), ) -> Option<&Option> { - self.persisted_validation_data.get(&key).map(|v| &v.0) + self.persisted_validation_data.get(&key) } pub(crate) fn cache_persisted_validation_data( @@ -211,14 +151,14 @@ impl RequestResultCache { key: (Hash, ParaId, OccupiedCoreAssumption), data: Option, ) { - self.persisted_validation_data.insert(key, ResidentSizeOf(data)); + self.persisted_validation_data.put(key, data); } pub(crate) fn assumed_validation_data( &mut self, key: (Hash, ParaId, Hash), ) -> Option<&Option<(PersistedValidationData, ValidationCodeHash)>> { - self.assumed_validation_data.get(&(key.1, key.2)).map(|v| &v.0) + self.assumed_validation_data.get(&(key.1, key.2)) } pub(crate) fn cache_assumed_validation_data( @@ -226,14 +166,14 @@ impl RequestResultCache { key: (ParaId, Hash), data: Option<(PersistedValidationData, ValidationCodeHash)>, ) { - self.assumed_validation_data.insert(key, ResidentSizeOf(data)); + self.assumed_validation_data.put(key, data); } pub(crate) fn check_validation_outputs( &mut self, key: (Hash, ParaId, CandidateCommitments), ) -> Option<&bool> { - self.check_validation_outputs.get(&key).map(|v| &v.0) + self.check_validation_outputs.get(&key) } pub(crate) fn cache_check_validation_outputs( @@ -241,11 +181,11 @@ impl RequestResultCache { key: (Hash, ParaId, CandidateCommitments), value: bool, ) { - self.check_validation_outputs.insert(key, ResidentSizeOf(value)); + self.check_validation_outputs.put(key, value); } pub(crate) fn session_index_for_child(&mut self, relay_parent: &Hash) -> Option<&SessionIndex> { - self.session_index_for_child.get(relay_parent).map(|v| &v.0) + self.session_index_for_child.get(relay_parent) } pub(crate) fn cache_session_index_for_child( @@ -253,14 +193,14 @@ impl RequestResultCache { relay_parent: Hash, index: SessionIndex, ) { - self.session_index_for_child.insert(relay_parent, ResidentSizeOf(index)); + self.session_index_for_child.put(relay_parent, index); } pub(crate) fn validation_code( &mut self, key: (Hash, ParaId, OccupiedCoreAssumption), ) -> Option<&Option> { - self.validation_code.get(&key).map(|v| &v.0) + self.validation_code.get(&key) } pub(crate) fn cache_validation_code( @@ -268,7 +208,7 @@ impl RequestResultCache { key: (Hash, ParaId, OccupiedCoreAssumption), value: Option, ) { - self.validation_code.insert(key, ResidentSizeOf(value)); + self.validation_code.put(key, value); } // the actual key is `ValidationCodeHash` (`Hash` is ignored), @@ -277,7 +217,7 @@ impl RequestResultCache { &mut self, key: (Hash, ValidationCodeHash), ) -> Option<&Option> { - self.validation_code_by_hash.get(&key.1).map(|v| &v.0) + self.validation_code_by_hash.get(&key.1) } pub(crate) fn cache_validation_code_by_hash( @@ -285,14 +225,14 @@ impl RequestResultCache { key: ValidationCodeHash, value: Option, ) { - self.validation_code_by_hash.insert(key, ResidentSizeOf(value)); + self.validation_code_by_hash.put(key, value); } pub(crate) fn candidate_pending_availability( &mut self, key: (Hash, ParaId), ) -> Option<&Option> { - self.candidate_pending_availability.get(&key).map(|v| &v.0) + self.candidate_pending_availability.get(&key) } pub(crate) fn cache_candidate_pending_availability( @@ -300,11 +240,11 @@ impl RequestResultCache { key: (Hash, ParaId), value: Option, ) { - self.candidate_pending_availability.insert(key, ResidentSizeOf(value)); + self.candidate_pending_availability.put(key, value); } pub(crate) fn candidate_events(&mut self, relay_parent: &Hash) -> Option<&Vec> { - self.candidate_events.get(relay_parent).map(|v| &v.0) + self.candidate_events.get(relay_parent) } pub(crate) fn cache_candidate_events( @@ -312,22 +252,22 @@ impl RequestResultCache { relay_parent: Hash, events: Vec, ) { - self.candidate_events.insert(relay_parent, ResidentSizeOf(events)); + self.candidate_events.put(relay_parent, events); } pub(crate) fn session_info(&mut self, key: SessionIndex) -> Option<&SessionInfo> { - self.session_info.get(&key).map(|v| &v.0) + self.session_info.get(&key) } pub(crate) fn cache_session_info(&mut self, key: SessionIndex, value: SessionInfo) { - self.session_info.insert(key, ResidentSizeOf(value)); + self.session_info.put(key, value); } pub(crate) fn dmq_contents( &mut self, key: (Hash, ParaId), ) -> Option<&Vec>> { - self.dmq_contents.get(&key).map(|v| &v.0) + self.dmq_contents.get(&key) } pub(crate) fn cache_dmq_contents( @@ -335,14 +275,14 @@ impl RequestResultCache { key: (Hash, ParaId), value: Vec>, ) { - self.dmq_contents.insert(key, ResidentSizeOf(value)); + self.dmq_contents.put(key, value); } pub(crate) fn inbound_hrmp_channels_contents( &mut self, key: (Hash, ParaId), ) -> Option<&BTreeMap>>> { - self.inbound_hrmp_channels_contents.get(&key).map(|v| &v.0) + self.inbound_hrmp_channels_contents.get(&key) } pub(crate) fn cache_inbound_hrmp_channel_contents( @@ -350,22 +290,22 @@ impl RequestResultCache { key: (Hash, ParaId), value: BTreeMap>>, ) { - self.inbound_hrmp_channels_contents.insert(key, ResidentSizeOf(value)); + self.inbound_hrmp_channels_contents.put(key, value); } pub(crate) fn current_babe_epoch(&mut self, relay_parent: &Hash) -> Option<&Epoch> { - self.current_babe_epoch.get(relay_parent).map(|v| &v.0) + self.current_babe_epoch.get(relay_parent) } pub(crate) fn cache_current_babe_epoch(&mut self, relay_parent: Hash, epoch: Epoch) { - self.current_babe_epoch.insert(relay_parent, DoesNotAllocate(epoch)); + self.current_babe_epoch.put(relay_parent, epoch); } pub(crate) fn on_chain_votes( &mut self, relay_parent: &Hash, ) -> Option<&Option> { - self.on_chain_votes.get(relay_parent).map(|v| &v.0) + self.on_chain_votes.get(relay_parent) } pub(crate) fn cache_on_chain_votes( @@ -373,14 +313,14 @@ impl RequestResultCache { relay_parent: Hash, scraped: Option, ) { - self.on_chain_votes.insert(relay_parent, ResidentSizeOf(scraped)); + self.on_chain_votes.put(relay_parent, scraped); } pub(crate) fn pvfs_require_precheck( &mut self, relay_parent: &Hash, ) -> Option<&Vec> { - self.pvfs_require_precheck.get(relay_parent).map(|v| &v.0) + self.pvfs_require_precheck.get(relay_parent) } pub(crate) fn cache_pvfs_require_precheck( @@ -388,14 +328,14 @@ impl RequestResultCache { relay_parent: Hash, pvfs: Vec, ) { - self.pvfs_require_precheck.insert(relay_parent, ResidentSizeOf(pvfs)) + self.pvfs_require_precheck.put(relay_parent, pvfs); } pub(crate) fn validation_code_hash( &mut self, key: (Hash, ParaId, OccupiedCoreAssumption), ) -> Option<&Option> { - self.validation_code_hash.get(&key).map(|v| &v.0) + self.validation_code_hash.get(&key) } pub(crate) fn cache_validation_code_hash( @@ -403,22 +343,22 @@ impl RequestResultCache { key: (Hash, ParaId, OccupiedCoreAssumption), value: Option, ) { - self.validation_code_hash.insert(key, ResidentSizeOf(value)); + self.validation_code_hash.put(key, value); } pub(crate) fn version(&mut self, relay_parent: &Hash) -> Option<&u32> { - self.version.get(&relay_parent).map(|v| &v.0) + self.version.get(relay_parent) } pub(crate) fn cache_version(&mut self, key: Hash, value: u32) { - self.version.insert(key, ResidentSizeOf(value)); + self.version.put(key, value); } pub(crate) fn disputes( &mut self, relay_parent: &Hash, ) -> Option<&Vec<(SessionIndex, CandidateHash, DisputeState)>> { - self.disputes.get(relay_parent).map(|v| &v.0) + self.disputes.get(relay_parent) } pub(crate) fn cache_disputes( @@ -426,7 +366,7 @@ impl RequestResultCache { relay_parent: Hash, value: Vec<(SessionIndex, CandidateHash, DisputeState)>, ) { - self.disputes.insert(relay_parent, ResidentSizeOf(value)); + self.disputes.put(relay_parent, value); } } diff --git a/node/core/runtime-api/src/lib.rs b/node/core/runtime-api/src/lib.rs index 36355b5759e6..de42ace3af0c 100644 --- a/node/core/runtime-api/src/lib.rs +++ b/node/core/runtime-api/src/lib.rs @@ -268,7 +268,7 @@ where let (sender, receiver) = oneshot::channel(); // TODO: make the cache great again https://github.com/paritytech/polkadot/issues/5546 - let request = match self.query_cache(relay_parent.clone(), request) { + let request = match self.query_cache(relay_parent, request) { Some(request) => request, None => return, }; diff --git a/node/core/runtime-api/src/tests.rs b/node/core/runtime-api/src/tests.rs index 2fab84179433..81629d5b2754 100644 --- a/node/core/runtime-api/src/tests.rs +++ b/node/core/runtime-api/src/tests.rs @@ -89,7 +89,7 @@ sp_api::mock_impl_runtime_apis! { } fn availability_cores(&self) -> Vec { - let _ = self.availability_cores_wait.lock().unwrap(); + let _lock = self.availability_cores_wait.lock().unwrap(); self.availability_cores.clone() } @@ -522,10 +522,10 @@ fn requests_session_index_for_child() { fn dummy_session_info() -> SessionInfo { SessionInfo { - validators: vec![], + validators: Default::default(), discovery_keys: vec![], assignment_keys: vec![], - validator_groups: vec![], + validator_groups: Default::default(), n_cores: 4u32, zeroth_delay_tranche_width: 0u32, relay_vrf_modulo_samples: 0u32, diff --git a/node/gum/Cargo.toml b/node/gum/Cargo.toml index c9338cd71a81..13cb9954df43 100644 --- a/node/gum/Cargo.toml +++ b/node/gum/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "tracing-gum" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true description = "Stick logs together with the TraceID as provided by tempo" [dependencies] diff --git a/node/gum/proc-macro/Cargo.toml b/node/gum/proc-macro/Cargo.toml index 7fa597f759fe..fccd4d218121 100644 --- a/node/gum/proc-macro/Cargo.toml +++ b/node/gum/proc-macro/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "tracing-gum-proc-macro" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true description = "Generate an overseer including builder pattern and message wrapper from a single annotated struct definition." [package.metadata.docs.rs] diff --git a/node/jaeger/Cargo.toml b/node/jaeger/Cargo.toml index a4a20fb5374b..ae8f10363277 100644 --- a/node/jaeger/Cargo.toml +++ b/node/jaeger/Cargo.toml @@ -1,19 +1,19 @@ [package] name = "polkadot-node-jaeger" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true description = "Polkadot Jaeger primitives, but equally useful for Grafana/Tempo" [dependencies] -async-std = "1.11.0" mick-jaeger = "0.1.8" lazy_static = "1.4" parking_lot = "0.12.0" polkadot-primitives = { path = "../../primitives" } polkadot-node-primitives = { path = "../primitives" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } thiserror = "1.0.31" +tokio = "1.22.0" log = "0.4.17" parity-scale-codec = { version = "3.1.5", default-features = false } diff --git a/node/jaeger/src/lib.rs b/node/jaeger/src/lib.rs index 5af77764d9c8..f33563a3d752 100644 --- a/node/jaeger/src/lib.rs +++ b/node/jaeger/src/lib.rs @@ -129,7 +129,7 @@ impl Jaeger { "jaeger-collector", Some("jaeger"), Box::pin(async move { - match async_std::net::UdpSocket::bind("0.0.0.0:0").await { + match tokio::net::UdpSocket::bind("0.0.0.0:0").await { Ok(udp_socket) => loop { let buf = traces_out.next().await; // UDP sending errors happen only either if the API is misused or in case of missing privilege. diff --git a/node/malus/Cargo.toml b/node/malus/Cargo.toml index 49271c4e7c4c..2a27c613868f 100644 --- a/node/malus/Cargo.toml +++ b/node/malus/Cargo.toml @@ -2,9 +2,9 @@ name = "polkadot-test-malus" description = "Misbehaving nodes for local testnets, system and Simnet tests." license = "GPL-3.0-only" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true readme = "README.md" publish = false @@ -23,12 +23,11 @@ polkadot-node-core-backing = { path = "../core/backing" } polkadot-node-primitives = { path = "../primitives" } polkadot-primitives = { path = "../../primitives" } polkadot-node-core-pvf = { path = "../core/pvf" } -parity-util-mem = { version = "0.12.0", default-features = false, features = ["jemalloc-global"] } color-eyre = { version = "0.6.1", default-features = false } assert_matches = "1.5" async-trait = "0.1.57" -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } clap = { version = "4.0.9", features = ["derive"] } futures = "0.3.21" futures-timer = "3.0.2" @@ -41,5 +40,5 @@ default = [] [dev-dependencies] polkadot-node-subsystem-test-helpers = { path = "../subsystem-test-helpers" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures = { version = "0.3.21", features = ["thread-pool"] } diff --git a/node/metrics/Cargo.toml b/node/metrics/Cargo.toml index 589c9440b3b6..e97da1e56fb4 100644 --- a/node/metrics/Cargo.toml +++ b/node/metrics/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "polkadot-node-metrics" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" description = "Subsystem metric helpers" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -13,11 +13,11 @@ gum = { package = "tracing-gum", path = "../gum" } metered = { package = "prioritized-metered-channel", version = "0.2.0" } # Both `sc-service` and `sc-cli` are required by runtime metrics `logger_hook()`. -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } codec = { package = "parity-scale-codec", version = "3.0.0" } primitives = { package = "polkadot-primitives", path = "../../primitives/" } bs58 = { version = "0.4.0", features = ["alloc"] } @@ -28,12 +28,12 @@ assert_cmd = "2.0.4" nix = "0.24.1" tempfile = "3.2.0" hyper = { version = "0.14.20", default-features = false, features = ["http1", "tcp"] } -tokio = "1.19.2" +tokio = "1.22.0" polkadot-test-service = { path = "../test/service", features=["runtime-metrics"]} -substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } prometheus-parse = {version = "0.2.2"} [features] diff --git a/node/metrics/src/metronome.rs b/node/metrics/src/metronome.rs index 9184f7ac20ad..ac47e20319d8 100644 --- a/node/metrics/src/metronome.rs +++ b/node/metrics/src/metronome.rs @@ -49,7 +49,7 @@ impl futures::Stream for Metronome { loop { match self.state { MetronomeState::SetAlarm => { - let val = self.period.clone(); + let val = self.period; self.delay.reset(val); self.state = MetronomeState::Snooze; }, diff --git a/node/network/approval-distribution/Cargo.toml b/node/network/approval-distribution/Cargo.toml index de6d13f551c7..c743f3b7dc36 100644 --- a/node/network/approval-distribution/Cargo.toml +++ b/node/network/approval-distribution/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-approval-distribution" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] polkadot-node-primitives = { path = "../../primitives" } @@ -16,8 +16,8 @@ futures = "0.3.21" gum = { package = "tracing-gum", path = "../../gum" } [dev-dependencies] -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.31" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.36" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } diff --git a/node/network/approval-distribution/src/lib.rs b/node/network/approval-distribution/src/lib.rs index 5afae66ae818..bf8a60fcefba 100644 --- a/node/network/approval-distribution/src/lib.rs +++ b/node/network/approval-distribution/src/lib.rs @@ -24,6 +24,7 @@ use futures::{channel::oneshot, FutureExt as _}; use polkadot_node_network_protocol::{ self as net_protocol, grid_topology::{RandomRouting, RequiredRouting, SessionGridTopologies, SessionGridTopology}, + peer_set::MAX_NOTIFICATION_SIZE, v1 as protocol_v1, PeerId, UnifiedReputationChange as Rep, Versioned, View, }; use polkadot_node_primitives::approval::{ @@ -309,7 +310,7 @@ enum MessageSource { impl MessageSource { fn peer_id(&self) -> Option { match self { - Self::Peer(id) => Some(id.clone()), + Self::Peer(id) => Some(*id), Self::Local => None, } } @@ -389,7 +390,7 @@ impl State { ) { let mut new_hashes = HashSet::new(); for meta in &metas { - match self.blocks.entry(meta.hash.clone()) { + match self.blocks.entry(meta.hash) { hash_map::Entry::Vacant(entry) => { let candidates_count = meta.candidates.len(); let mut candidates = Vec::with_capacity(candidates_count); @@ -398,7 +399,7 @@ impl State { entry.insert(BlockEntry { known_by: HashMap::new(), number: meta.number, - parent_hash: meta.parent_hash.clone(), + parent_hash: meta.parent_hash, knowledge: Knowledge::default(), candidates, session: meta.session, @@ -406,7 +407,7 @@ impl State { self.topologies.inc_session_refs(meta.session); - new_hashes.insert(meta.hash.clone()); + new_hashes.insert(meta.hash); // In case there are duplicates, we should only set this if the entry // was vacant. @@ -433,7 +434,7 @@ impl State { &mut self.blocks, &self.topologies, self.peer_views.len(), - peer_id.clone(), + *peer_id, view_intersection, rng, ) @@ -563,10 +564,8 @@ impl State { "Pending assignment", ); - pending.push(( - peer_id.clone(), - PendingMessage::Assignment(assignment, claimed_index), - )); + pending + .push((peer_id, PendingMessage::Assignment(assignment, claimed_index))); continue } @@ -574,7 +573,7 @@ impl State { self.import_and_circulate_assignment( ctx, metrics, - MessageSource::Peer(peer_id.clone()), + MessageSource::Peer(peer_id), assignment, claimed_index, rng, @@ -604,7 +603,7 @@ impl State { "Pending approval", ); - pending.push((peer_id.clone(), PendingMessage::Approval(approval_vote))); + pending.push((peer_id, PendingMessage::Approval(approval_vote))); continue } @@ -612,7 +611,7 @@ impl State { self.import_and_circulate_approval( ctx, metrics, - MessageSource::Peer(peer_id.clone()), + MessageSource::Peer(peer_id), approval_vote, ) .await; @@ -663,7 +662,7 @@ impl State { &mut self.blocks, &self.topologies, self.peer_views.len(), - peer_id.clone(), + peer_id, view, rng, ) @@ -709,7 +708,7 @@ impl State { ) where R: CryptoRng + Rng, { - let block_hash = assignment.block_hash.clone(); + let block_hash = assignment.block_hash; let validator_index = assignment.validator; let entry = match self.blocks.get_mut(&block_hash) { @@ -737,7 +736,7 @@ impl State { if let Some(peer_id) = source.peer_id() { // check if our knowledge of the peer already contains this assignment - match entry.known_by.entry(peer_id.clone()) { + match entry.known_by.entry(peer_id) { hash_map::Entry::Occupied(mut peer_knowledge) => { let peer_knowledge = peer_knowledge.get_mut(); if peer_knowledge.contains(&message_subject, message_kind) { @@ -761,13 +760,13 @@ impl State { ?message_subject, "Assignment from a peer is out of view", ); - modify_reputation(ctx.sender(), peer_id.clone(), COST_UNEXPECTED_MESSAGE).await; + modify_reputation(ctx.sender(), peer_id, COST_UNEXPECTED_MESSAGE).await; }, } // if the assignment is known to be valid, reward the peer if entry.knowledge.contains(&message_subject, message_kind) { - modify_reputation(ctx.sender(), peer_id.clone(), BENEFIT_VALID_MESSAGE).await; + modify_reputation(ctx.sender(), peer_id, BENEFIT_VALID_MESSAGE).await; if let Some(peer_knowledge) = entry.known_by.get_mut(&peer_id) { gum::trace!(target: LOG_TARGET, ?peer_id, ?message_subject, "Known assignment"); peer_knowledge.received.insert(message_subject, message_kind); @@ -803,8 +802,7 @@ impl State { ); match result { AssignmentCheckResult::Accepted => { - modify_reputation(ctx.sender(), peer_id.clone(), BENEFIT_VALID_MESSAGE_FIRST) - .await; + modify_reputation(ctx.sender(), peer_id, BENEFIT_VALID_MESSAGE_FIRST).await; entry.knowledge.known_messages.insert(message_subject.clone(), message_kind); if let Some(peer_knowledge) = entry.known_by.get_mut(&peer_id) { peer_knowledge.received.insert(message_subject.clone(), message_kind); @@ -970,7 +968,7 @@ impl State { source: MessageSource, vote: IndirectSignedApprovalVote, ) { - let block_hash = vote.block_hash.clone(); + let block_hash = vote.block_hash; let validator_index = vote.validator; let candidate_index = vote.candidate_index; @@ -1003,7 +1001,7 @@ impl State { } // check if our knowledge of the peer already contains this approval - match entry.known_by.entry(peer_id.clone()) { + match entry.known_by.entry(peer_id) { hash_map::Entry::Occupied(mut knowledge) => { let peer_knowledge = knowledge.get_mut(); if peer_knowledge.contains(&message_subject, message_kind) { @@ -1027,14 +1025,14 @@ impl State { ?message_subject, "Approval from a peer is out of view", ); - modify_reputation(ctx.sender(), peer_id.clone(), COST_UNEXPECTED_MESSAGE).await; + modify_reputation(ctx.sender(), peer_id, COST_UNEXPECTED_MESSAGE).await; }, } // if the approval is known to be valid, reward the peer if entry.knowledge.contains(&message_subject, message_kind) { gum::trace!(target: LOG_TARGET, ?peer_id, ?message_subject, "Known approval"); - modify_reputation(ctx.sender(), peer_id.clone(), BENEFIT_VALID_MESSAGE).await; + modify_reputation(ctx.sender(), peer_id, BENEFIT_VALID_MESSAGE).await; if let Some(peer_knowledge) = entry.known_by.get_mut(&peer_id) { peer_knowledge.received.insert(message_subject.clone(), message_kind); } @@ -1065,8 +1063,7 @@ impl State { ); match result { ApprovalCheckResult::Accepted => { - modify_reputation(ctx.sender(), peer_id.clone(), BENEFIT_VALID_MESSAGE_FIRST) - .await; + modify_reputation(ctx.sender(), peer_id, BENEFIT_VALID_MESSAGE_FIRST).await; entry.knowledge.insert(message_subject.clone(), message_kind); if let Some(peer_knowledge) = entry.known_by.get_mut(&peer_id) { @@ -1301,7 +1298,7 @@ impl State { break } - let peer_knowledge = entry.known_by.entry(peer_id.clone()).or_default(); + let peer_knowledge = entry.known_by.entry(peer_id).or_default(); let topology = topologies.get_topology(entry.session); @@ -1335,13 +1332,12 @@ impl State { } } - let message_subject = - MessageSubject(block.clone(), candidate_index, validator.clone()); + let message_subject = MessageSubject(block, candidate_index, *validator); let assignment_message = ( IndirectAssignmentCert { - block_hash: block.clone(), - validator: validator.clone(), + block_hash: block, + validator: *validator, cert: message_state.approval_state.assignment_cert().clone(), }, candidate_index, @@ -1350,8 +1346,8 @@ impl State { let approval_message = message_state.approval_state.approval_signature().map(|signature| { IndirectSignedApprovalVote { - block_hash: block.clone(), - validator: validator.clone(), + block_hash: block, + validator: *validator, candidate_index, signature, } @@ -1374,7 +1370,7 @@ impl State { } } - block = entry.parent_hash.clone(); + block = entry.parent_hash; } } @@ -1386,14 +1382,7 @@ impl State { "Sending assignments to unified peer", ); - sender - .send_message(NetworkBridgeTxMessage::SendValidationMessage( - vec![peer_id.clone()], - Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution( - protocol_v1::ApprovalDistributionMessage::Assignments(assignments_to_send), - )), - )) - .await; + send_assignments_batched(sender, assignments_to_send, peer_id).await; } if !approvals_to_send.is_empty() { @@ -1404,14 +1393,7 @@ impl State { "Sending approvals to unified peer", ); - sender - .send_message(NetworkBridgeTxMessage::SendValidationMessage( - vec![peer_id], - Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution( - protocol_v1::ApprovalDistributionMessage::Approvals(approvals_to_send), - )), - )) - .await; + send_approvals_batched(sender, approvals_to_send, peer_id).await; } } @@ -1558,13 +1540,12 @@ async fn adjust_required_routing_and_propagate ApprovalDistribution { SpawnedSubsystem { name: "approval-distribution-subsystem", future } } } + +/// Ensures the batch size is always at least 1 element. +const fn ensure_size_not_zero(size: usize) -> usize { + if 0 == size { + panic!("Batch size must be at least 1 (MAX_NOTIFICATION_SIZE constant is too low)",); + } + + size +} + +/// The maximum amount of assignments per batch is 33% of maximum allowed by protocol. +/// This is an arbitrary value. Bumping this up increases the maximum amount of approvals or assignments +/// we send in a single message to peers. Exceeding `MAX_NOTIFICATION_SIZE` will violate the protocol +/// configuration. +pub const MAX_ASSIGNMENT_BATCH_SIZE: usize = ensure_size_not_zero( + MAX_NOTIFICATION_SIZE as usize / + std::mem::size_of::<(IndirectAssignmentCert, CandidateIndex)>() / + 3, +); + +/// The maximum amount of approvals per batch is 33% of maximum allowed by protocol. +pub const MAX_APPROVAL_BATCH_SIZE: usize = ensure_size_not_zero( + MAX_NOTIFICATION_SIZE as usize / std::mem::size_of::() / 3, +); + +/// Send assignments while honoring the `max_notification_size` of the protocol. +/// +/// Splitting the messages into multiple notifications allows more granular processing at the +/// destination, such that the subsystem doesn't get stuck for long processing a batch +/// of assignments and can `select!` other tasks. +pub(crate) async fn send_assignments_batched( + sender: &mut impl overseer::ApprovalDistributionSenderTrait, + assignments: Vec<(IndirectAssignmentCert, CandidateIndex)>, + peer: PeerId, +) { + let mut batches = assignments.into_iter().peekable(); + + while batches.peek().is_some() { + let batch: Vec<_> = batches.by_ref().take(MAX_ASSIGNMENT_BATCH_SIZE).collect(); + + sender + .send_message(NetworkBridgeTxMessage::SendValidationMessage( + vec![peer], + Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution( + protocol_v1::ApprovalDistributionMessage::Assignments(batch), + )), + )) + .await; + } +} + +/// Send approvals while honoring the `max_notification_size` of the protocol. +pub(crate) async fn send_approvals_batched( + sender: &mut impl overseer::ApprovalDistributionSenderTrait, + approvals: Vec, + peer: PeerId, +) { + let mut batches = approvals.into_iter().peekable(); + + while batches.peek().is_some() { + let batch: Vec<_> = batches.by_ref().take(MAX_APPROVAL_BATCH_SIZE).collect(); + + sender + .send_message(NetworkBridgeTxMessage::SendValidationMessage( + vec![peer], + Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution( + protocol_v1::ApprovalDistributionMessage::Approvals(batch), + )), + )) + .await; + } +} diff --git a/node/network/approval-distribution/src/metrics.rs b/node/network/approval-distribution/src/metrics.rs index c0887b25f7f4..b14e54c57403 100644 --- a/node/network/approval-distribution/src/metrics.rs +++ b/node/network/approval-distribution/src/metrics.rs @@ -127,7 +127,7 @@ impl MetricsTrait for Metrics { prometheus::Histogram::with_opts(prometheus::HistogramOpts::new( "polkadot_parachain_time_unify_with_peer", "Time spent within fn `unify_with_peer`.", - ))?, + ).buckets(vec![0.000625, 0.00125,0.0025, 0.005, 0.0075, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0,]))?, registry, )?, time_import_pending_now_known: prometheus::register( diff --git a/node/network/approval-distribution/src/tests.rs b/node/network/approval-distribution/src/tests.rs index 73aa461752ba..567cf22f23f1 100644 --- a/node/network/approval-distribution/src/tests.rs +++ b/node/network/approval-distribution/src/tests.rs @@ -2276,3 +2276,147 @@ fn resends_messages_periodically() { virtual_overseer }); } + +fn batch_test_round(message_count: usize) { + use polkadot_node_subsystem::SubsystemContext; + let pool = sp_core::testing::TaskExecutor::new(); + let mut state = State::default(); + + let (mut context, mut virtual_overseer) = test_helpers::make_subsystem_context(pool.clone()); + let subsystem = ApprovalDistribution::new(Default::default()); + let mut rng = rand_chacha::ChaCha12Rng::seed_from_u64(12345); + let mut sender = context.sender().clone(); + let subsystem = subsystem.run_inner(context, &mut state, &mut rng); + + let test_fut = async move { + let overseer = &mut virtual_overseer; + let validators = 0..message_count; + let assignments: Vec<_> = validators + .clone() + .map(|index| (fake_assignment_cert(Hash::zero(), ValidatorIndex(index as u32)), 0)) + .collect(); + + let approvals: Vec<_> = validators + .map(|index| IndirectSignedApprovalVote { + block_hash: Hash::zero(), + candidate_index: 0, + validator: ValidatorIndex(index as u32), + signature: dummy_signature(), + }) + .collect(); + + let peer = PeerId::random(); + send_assignments_batched(&mut sender, assignments.clone(), peer).await; + send_approvals_batched(&mut sender, approvals.clone(), peer).await; + + // Check expected assignments batches. + for assignment_index in (0..assignments.len()).step_by(super::MAX_ASSIGNMENT_BATCH_SIZE) { + assert_matches!( + overseer_recv(overseer).await, + AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage( + peers, + Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution( + protocol_v1::ApprovalDistributionMessage::Assignments(sent_assignments) + )) + )) => { + // Last batch should cover all remaining messages. + if sent_assignments.len() < super::MAX_ASSIGNMENT_BATCH_SIZE { + assert_eq!(sent_assignments.len() + assignment_index, assignments.len()); + } else { + assert_eq!(sent_assignments.len(), super::MAX_ASSIGNMENT_BATCH_SIZE); + } + + assert_eq!(peers.len(), 1); + + for (message_index, assignment) in sent_assignments.iter().enumerate() { + assert_eq!(assignment.0, assignments[assignment_index + message_index].0); + assert_eq!(assignment.1, 0); + } + } + ); + } + + // Check approval vote batching. + for approval_index in (0..approvals.len()).step_by(super::MAX_APPROVAL_BATCH_SIZE) { + assert_matches!( + overseer_recv(overseer).await, + AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessage( + peers, + Versioned::V1(protocol_v1::ValidationProtocol::ApprovalDistribution( + protocol_v1::ApprovalDistributionMessage::Approvals(sent_approvals) + )) + )) => { + // Last batch should cover all remaining messages. + if sent_approvals.len() < super::MAX_APPROVAL_BATCH_SIZE { + assert_eq!(sent_approvals.len() + approval_index, approvals.len()); + } else { + assert_eq!(sent_approvals.len(), super::MAX_APPROVAL_BATCH_SIZE); + } + + assert_eq!(peers.len(), 1); + + for (message_index, approval) in sent_approvals.iter().enumerate() { + assert_eq!(approval, &approvals[approval_index + message_index]); + } + } + ); + } + virtual_overseer + }; + + futures::pin_mut!(test_fut); + futures::pin_mut!(subsystem); + + executor::block_on(future::join( + async move { + let mut overseer = test_fut.await; + overseer + .send(FromOrchestra::Signal(OverseerSignal::Conclude)) + .timeout(TIMEOUT) + .await + .expect("Conclude send timeout"); + }, + subsystem, + )); +} + +#[test] +fn batch_sending_1_msg() { + batch_test_round(1); +} + +#[test] +fn batch_sending_exactly_one_batch() { + batch_test_round(super::MAX_APPROVAL_BATCH_SIZE); + batch_test_round(super::MAX_ASSIGNMENT_BATCH_SIZE); +} + +#[test] +fn batch_sending_partial_batch() { + batch_test_round(super::MAX_APPROVAL_BATCH_SIZE * 2 + 4); + batch_test_round(super::MAX_ASSIGNMENT_BATCH_SIZE * 2 + 4); +} + +#[test] +fn batch_sending_multiple_same_len() { + batch_test_round(super::MAX_APPROVAL_BATCH_SIZE * 10); + batch_test_round(super::MAX_ASSIGNMENT_BATCH_SIZE * 10); +} + +#[test] +fn batch_sending_half_batch() { + batch_test_round(super::MAX_APPROVAL_BATCH_SIZE / 2); + batch_test_round(super::MAX_ASSIGNMENT_BATCH_SIZE / 2); +} + +#[test] +#[should_panic] +fn const_batch_size_panics_if_zero() { + crate::ensure_size_not_zero(0); +} + +#[test] +fn const_ensure_size_not_zero() { + crate::ensure_size_not_zero(super::MAX_ASSIGNMENT_BATCH_SIZE); + crate::ensure_size_not_zero(super::MAX_APPROVAL_BATCH_SIZE); +} diff --git a/node/network/availability-distribution/Cargo.toml b/node/network/availability-distribution/Cargo.toml index 886a22001225..a90290bb2ed9 100644 --- a/node/network/availability-distribution/Cargo.toml +++ b/node/network/availability-distribution/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-availability-distribution" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -14,8 +14,8 @@ polkadot-node-network-protocol = { path = "../../network/protocol" } polkadot-node-subsystem = { path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-primitives = { path = "../../primitives" } -sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } thiserror = "1.0.31" rand = "0.8.5" derive_more = "0.99.17" @@ -24,10 +24,10 @@ fatality = "0.0.6" [dev-dependencies] polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } -sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures-timer = "3.0.2" assert_matches = "1.4.0" polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } diff --git a/node/network/availability-distribution/src/tests/mock.rs b/node/network/availability-distribution/src/tests/mock.rs index 86be0a1e230d..15ea1ab1bc53 100644 --- a/node/network/availability-distribution/src/tests/mock.rs +++ b/node/network/availability-distribution/src/tests/mock.rs @@ -24,8 +24,8 @@ use polkadot_erasure_coding::{branches, obtain_chunks_v1 as obtain_chunks}; use polkadot_node_primitives::{AvailableData, BlockData, ErasureChunk, PoV, Proof}; use polkadot_primitives::v2::{ CandidateCommitments, CandidateDescriptor, CandidateHash, CommittedCandidateReceipt, - GroupIndex, Hash, HeadData, Id as ParaId, OccupiedCore, PersistedValidationData, SessionInfo, - ValidatorIndex, + GroupIndex, Hash, HeadData, Id as ParaId, IndexedVec, OccupiedCore, PersistedValidationData, + SessionInfo, ValidatorIndex, }; use polkadot_primitives_test_helpers::{ dummy_collator, dummy_collator_signature, dummy_hash, dummy_validation_code, @@ -43,10 +43,11 @@ pub fn make_session_info() -> SessionInfo { Sr25519Keyring::One, ]; - let validator_groups: Vec> = [vec![5, 0, 3], vec![1, 6, 2, 4]] - .iter() - .map(|g| g.into_iter().map(|v| ValidatorIndex(*v)).collect()) - .collect(); + let validator_groups: IndexedVec> = + [vec![5, 0, 3], vec![1, 6, 2, 4]] + .iter() + .map(|g| g.into_iter().map(|v| ValidatorIndex(*v)).collect()) + .collect(); SessionInfo { discovery_keys: validators.iter().map(|k| k.public().into()).collect(), diff --git a/node/network/availability-distribution/src/tests/state.rs b/node/network/availability-distribution/src/tests/state.rs index c021f1bfb81b..be77aa2d023c 100644 --- a/node/network/availability-distribution/src/tests/state.rs +++ b/node/network/availability-distribution/src/tests/state.rs @@ -51,7 +51,7 @@ use polkadot_primitives::v2::{ CandidateHash, CoreState, GroupIndex, Hash, Id as ParaId, ScheduledCore, SessionInfo, ValidatorIndex, }; -use test_helpers::{mock::make_ferdie_keystore, SingleItemSink}; +use test_helpers::mock::make_ferdie_keystore; use super::mock::{make_session_info, OccupiedCoreBuilder}; use crate::LOG_TARGET; @@ -295,7 +295,7 @@ impl TestState { } async fn overseer_signal( - mut tx: SingleItemSink>, + mut tx: mpsc::Sender>, msg: impl Into, ) { let msg = msg.into(); diff --git a/node/network/availability-recovery/Cargo.toml b/node/network/availability-recovery/Cargo.toml index b9bcefc781ea..fde5fba875e5 100644 --- a/node/network/availability-recovery/Cargo.toml +++ b/node/network/availability-recovery/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-availability-recovery" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -19,7 +19,7 @@ polkadot-node-subsystem = {path = "../../subsystem" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-network-protocol = { path = "../../network/protocol" } parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [dev-dependencies] assert_matches = "1.4.0" @@ -27,10 +27,10 @@ env_logger = "0.9.0" futures-timer = "3.0.2" log = "0.4.17" -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } diff --git a/node/network/availability-recovery/src/lib.rs b/node/network/availability-recovery/src/lib.rs index a07f4e0baa52..38acfbe88ff9 100644 --- a/node/network/availability-recovery/src/lib.rs +++ b/node/network/availability-recovery/src/lib.rs @@ -58,7 +58,7 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_util::request_session_info; use polkadot_primitives::v2::{ AuthorityDiscoveryId, BlakeTwo256, BlockNumber, CandidateHash, CandidateReceipt, GroupIndex, - Hash, HashT, SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, + Hash, HashT, IndexedVec, SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, }; mod error; @@ -134,7 +134,7 @@ struct RecoveryParams { validator_authority_keys: Vec, /// Validators relevant to this `RecoveryTask`. - validators: Vec, + validators: IndexedVec, /// The number of pieces needed. threshold: usize, @@ -338,8 +338,7 @@ impl RequestChunksFromValidators { index: validator_index, }; - let (req, res) = - OutgoingRequest::new(Recipient::Authority(validator), raw_request.clone()); + let (req, res) = OutgoingRequest::new(Recipient::Authority(validator), raw_request); requests.push(Requests::ChunkFetchingV1(req)); params.metrics.on_chunk_request_issued(); @@ -836,7 +835,7 @@ async fn handle_signal(state: &mut State, signal: OverseerSignal) -> SubsystemRe OverseerSignal::Conclude => Ok(true), OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { activated, .. }) => { // if activated is non-empty, set state.live_block to the highest block in `activated` - for activated in activated { + if let Some(activated) = activated { if activated.number > state.live_block.0 { state.live_block = (activated.number, activated.hash) } @@ -871,7 +870,7 @@ async fn launch_recovery_task( }; let phase = backing_group - .and_then(|g| session_info.validator_groups.get(g.0 as usize)) + .and_then(|g| session_info.validator_groups.get(g)) .map(|group| Source::RequestFromBackers(RequestFromBackers::new(group.clone()))) .unwrap_or_else(|| { Source::RequestChunks(RequestChunksFromValidators::new(params.validators.len() as _)) @@ -973,7 +972,7 @@ async fn query_full_data( ctx.send_message(AvailabilityStoreMessage::QueryAvailableData(candidate_hash, tx)) .await; - Ok(rx.await.map_err(error::Error::CanceledQueryFullData)?) + rx.await.map_err(error::Error::CanceledQueryFullData) } #[overseer::contextbounds(AvailabilityRecovery, prefix = self::overseer)] diff --git a/node/network/availability-recovery/src/tests.rs b/node/network/availability-recovery/src/tests.rs index 3e898088c7f9..c77278f645c1 100644 --- a/node/network/availability-recovery/src/tests.rs +++ b/node/network/availability-recovery/src/tests.rs @@ -36,7 +36,9 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_test_helpers::{make_subsystem_context, TestSubsystemContextHandle}; use polkadot_node_subsystem_util::TimeoutExt; -use polkadot_primitives::v2::{AuthorityDiscoveryId, Hash, HeadData, PersistedValidationData}; +use polkadot_primitives::v2::{ + AuthorityDiscoveryId, Hash, HeadData, IndexedVec, PersistedValidationData, ValidatorId, +}; use polkadot_primitives_test_helpers::{dummy_candidate_receipt, dummy_hash}; type VirtualOverseer = TestSubsystemContextHandle; @@ -179,7 +181,7 @@ impl Has { #[derive(Clone)] struct TestState { validators: Vec, - validator_public: Vec, + validator_public: IndexedVec, validator_authority_id: Vec, current: Hash, candidate: CandidateReceipt, @@ -218,7 +220,7 @@ impl TestState { validators: self.validator_public.clone(), discovery_keys: self.validator_authority_id.clone(), // all validators in the same group. - validator_groups: vec![(0..self.validators.len()).map(|i| ValidatorIndex(i as _)).collect()], + validator_groups: IndexedVec::>::from(vec![(0..self.validators.len()).map(|i| ValidatorIndex(i as _)).collect()]), assignment_keys: vec![], n_cores: 0, zeroth_delay_tranche_width: 0, @@ -402,7 +404,7 @@ impl TestState { } } -fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec { +fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> IndexedVec { val_ids.iter().map(|v| v.public().into()).collect() } diff --git a/node/network/bitfield-distribution/Cargo.toml b/node/network/bitfield-distribution/Cargo.toml index 0a26c57975c4..4e5377a1950f 100644 --- a/node/network/bitfield-distribution/Cargo.toml +++ b/node/network/bitfield-distribution/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-availability-bitfield-distribution" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -16,11 +16,11 @@ rand = "0.8" [dev-dependencies] polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } maplit = "1.0.2" log = "0.4.17" env_logger = "0.9.0" diff --git a/node/network/bitfield-distribution/src/lib.rs b/node/network/bitfield-distribution/src/lib.rs index 1b2167484b49..1bd9230a3787 100644 --- a/node/network/bitfield-distribution/src/lib.rs +++ b/node/network/bitfield-distribution/src/lib.rs @@ -233,7 +233,7 @@ impl BitfieldDistribution { })) => { let _timer = self.metrics.time_active_leaves_update(); - for activated in activated { + if let Some(activated) = activated { let relay_parent = activated.hash; gum::trace!(target: LOG_TARGET, ?relay_parent, "activated"); @@ -319,7 +319,7 @@ async fn handle_bitfield_distribution( } let validator_index = signed_availability.validator_index(); - let validator = if let Some(validator) = validator_set.get(*&validator_index.0 as usize) { + let validator = if let Some(validator) = validator_set.get(validator_index.0 as usize) { validator.clone() } else { gum::debug!(target: LOG_TARGET, validator_index = ?validator_index.0, "Could not find a validator for index"); @@ -395,7 +395,7 @@ async fn relay_message( }; if need_routing { - Some(peer.clone()) + Some(*peer) } else { None } @@ -412,7 +412,7 @@ async fn relay_message( // track the message as sent for this peer job_data .message_sent_to_peer - .entry(peer.clone()) + .entry(*peer) .or_default() .insert(validator.clone()); }); @@ -497,7 +497,7 @@ async fn process_incoming_peer_message( // Check if the peer already sent us a message for the validator denoted in the message earlier. // Must be done after validator index verification, in order to avoid storing an unbounded // number of set entries. - let received_set = job_data.message_received_from_peer.entry(origin.clone()).or_default(); + let received_set = job_data.message_received_from_peer.entry(origin).or_default(); if !received_set.contains(&validator) { received_set.insert(validator.clone()); @@ -656,7 +656,7 @@ async fn handle_peer_view_change( ) { let added = state .peer_views - .entry(origin.clone()) + .entry(origin) .or_default() .replace_difference(view) .cloned() @@ -681,11 +681,10 @@ async fn handle_peer_view_change( let delta_set: Vec<(ValidatorId, BitfieldGossipMessage)> = added .into_iter() .filter_map(|new_relay_parent_interest| { - if let Some(job_data) = (&*state).per_relay_parent.get(&new_relay_parent_interest) { + if let Some(job_data) = state.per_relay_parent.get(&new_relay_parent_interest) { // Send all jointly known messages for a validator (given the current relay parent) // to the peer `origin`... let one_per_validator = job_data.one_per_validator.clone(); - let origin = origin.clone(); Some(one_per_validator.into_iter().filter(move |(validator, _message)| { // ..except for the ones the peer already has. job_data.message_from_validator_needed_by_peer(&origin, validator) @@ -699,7 +698,7 @@ async fn handle_peer_view_change( .collect(); for (validator, message) in delta_set.into_iter() { - send_tracked_gossip_message(ctx, state, origin.clone(), validator, message).await; + send_tracked_gossip_message(ctx, state, origin, validator, message).await; } } @@ -727,11 +726,7 @@ async fn send_tracked_gossip_message( "Sending gossip message" ); - job_data - .message_sent_to_peer - .entry(dest.clone()) - .or_default() - .insert(validator.clone()); + job_data.message_sent_to_peer.entry(dest).or_default().insert(validator.clone()); ctx.send_message(NetworkBridgeTxMessage::SendValidationMessage( vec![dest], @@ -760,14 +755,14 @@ async fn query_basics( // query validators ctx.send_message(RuntimeApiMessage::Request( - relay_parent.clone(), + relay_parent, RuntimeApiRequest::Validators(validators_tx), )) .await; // query signing context ctx.send_message(RuntimeApiMessage::Request( - relay_parent.clone(), + relay_parent, RuntimeApiRequest::SessionIndexForChild(session_tx), )) .await; diff --git a/node/network/bridge/Cargo.toml b/node/network/bridge/Cargo.toml index 7802a83e2747..9627026b5d4e 100644 --- a/node/network/bridge/Cargo.toml +++ b/node/network/bridge/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-network-bridge" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] always-assert = "0.1" @@ -11,9 +11,9 @@ futures = "0.3.21" gum = { package = "tracing-gum", path = "../../gum" } polkadot-primitives = { path = "../../../primitives" } parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-node-subsystem = {path = "../../subsystem" } polkadot-overseer = { path = "../../overseer" } polkadot-node-network-protocol = { path = "../protocol" } @@ -26,7 +26,7 @@ thiserror = "1" [dev-dependencies] assert_matches = "1.4.0" polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures-timer = "3" polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } diff --git a/node/network/bridge/src/network.rs b/node/network/bridge/src/network.rs index 9b326cbbfb38..32dc79d25814 100644 --- a/node/network/bridge/src/network.rs +++ b/node/network/bridge/src/network.rs @@ -174,7 +174,7 @@ impl Network for Arc> { Ok(v) => v, Err(_) => continue, }; - NetworkService::add_known_address(&*self, peer_id.clone(), addr); + NetworkService::add_known_address(self, peer_id, addr); found_peer_id = Some(peer_id); } found_peer_id @@ -197,7 +197,7 @@ impl Network for Arc> { }; NetworkService::start_request( - &*self, + self, peer_id, req_protocol_names.get_name(protocol), payload, diff --git a/node/network/bridge/src/rx/mod.rs b/node/network/bridge/src/rx/mod.rs index a08596cd15ac..1d3052d3a218 100644 --- a/node/network/bridge/src/rx/mod.rs +++ b/node/network/bridge/src/rx/mod.rs @@ -125,7 +125,7 @@ where let future = run_network_in(self, ctx, network_stream) .map_err(|e| SubsystemError::with_origin("network-bridge", e)) .boxed(); - SpawnedSubsystem { name: "network-bridge-subsystem", future } + SpawnedSubsystem { name: "network-bridge-rx-subsystem", future } } } @@ -213,7 +213,7 @@ where PeerSet::Collation => &mut shared.collation_peers, }; - match peer_map.entry(peer.clone()) { + match peer_map.entry(peer) { hash_map::Entry::Occupied(_) => continue, hash_map::Entry::Vacant(vacant) => { vacant.insert(PeerData { view: View::default(), version }); @@ -234,12 +234,12 @@ where dispatch_validation_events_to_all( vec![ NetworkBridgeEvent::PeerConnected( - peer.clone(), + peer, role, version, maybe_authority, ), - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + NetworkBridgeEvent::PeerViewChange(peer, View::default()), ], &mut sender, ) @@ -259,12 +259,12 @@ where dispatch_collation_events_to_all( vec![ NetworkBridgeEvent::PeerConnected( - peer.clone(), + peer, role, version, maybe_authority, ), - NetworkBridgeEvent::PeerViewChange(peer.clone(), View::default()), + NetworkBridgeEvent::PeerViewChange(peer, View::default()), ], &mut sender, ) @@ -421,7 +421,7 @@ where Some(ValidationVersion::V1.into()) { handle_v1_peer_messages::( - remote.clone(), + remote, PeerSet::Validation, &mut shared.0.lock().validation_peers, v_messages, @@ -442,7 +442,7 @@ where }; for report in reports { - network_service.report_peer(remote.clone(), report); + network_service.report_peer(remote, report); } dispatch_validation_events_to_all(events, &mut sender).await; @@ -454,7 +454,7 @@ where Some(CollationVersion::V1.into()) { handle_v1_peer_messages::( - remote.clone(), + remote, PeerSet::Collation, &mut shared.0.lock().collation_peers, c_messages, @@ -475,7 +475,7 @@ where }; for report in reports { - network_service.report_peer(remote.clone(), report); + network_service.report_peer(remote, report); } dispatch_collation_events_to_all(events, &mut sender).await; @@ -566,7 +566,7 @@ where num_deactivated = %deactivated.len(), ); - for activated in activated { + if let Some(activated) = activated { let pos = live_heads .binary_search_by(|probe| probe.number.cmp(&activated.number).reverse()) .unwrap_or_else(|i| i); @@ -795,11 +795,11 @@ fn handle_v1_peer_messages>( } else { peer_data.view = new_view; - NetworkBridgeEvent::PeerViewChange(peer.clone(), peer_data.view.clone()) + NetworkBridgeEvent::PeerViewChange(peer, peer_data.view.clone()) } }, WireMessage::ProtocolMessage(message) => - NetworkBridgeEvent::PeerMessage(peer.clone(), message.into()), + NetworkBridgeEvent::PeerMessage(peer, message.into()), }) } diff --git a/node/network/bridge/src/tx/mod.rs b/node/network/bridge/src/tx/mod.rs index 47f095fdf273..32a0ecaf7510 100644 --- a/node/network/bridge/src/tx/mod.rs +++ b/node/network/bridge/src/tx/mod.rs @@ -90,7 +90,7 @@ where let future = run_network_out(self, ctx) .map_err(|e| SubsystemError::with_origin("network-bridge", e)) .boxed(); - SpawnedSubsystem { name: "network-bridge-subsystem", future } + SpawnedSubsystem { name: "network-bridge-tx-subsystem", future } } } diff --git a/node/network/collator-protocol/Cargo.toml b/node/network/collator-protocol/Cargo.toml index 141d28af869f..17a52be8eb44 100644 --- a/node/network/collator-protocol/Cargo.toml +++ b/node/network/collator-protocol/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-collator-protocol" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] always-assert = "0.1.2" @@ -11,9 +11,9 @@ futures = "0.3.21" futures-timer = "3" gum = { package = "tracing-gum", path = "../../gum" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-primitives = { path = "../../../primitives" } polkadot-node-network-protocol = { path = "../../network/protocol" } @@ -28,9 +28,9 @@ log = "0.4.17" env_logger = "0.9.0" assert_matches = "1.4.0" -sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } parity-scale-codec = { version = "3.1.5", features = ["std"] } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } diff --git a/node/network/collator-protocol/src/collator_side/mod.rs b/node/network/collator-protocol/src/collator_side/mod.rs index 4f2eea2ca747..f7b27583a6dd 100644 --- a/node/network/collator-protocol/src/collator_side/mod.rs +++ b/node/network/collator-protocol/src/collator_side/mod.rs @@ -448,10 +448,8 @@ async fn determine_our_validators( let rotation_info = get_group_rotation_info(ctx.sender(), relay_parent).await?; let current_group_index = rotation_info.group_for_core(core_index, cores); - let current_validators = groups - .get(current_group_index.0 as usize) - .map(|v| v.as_slice()) - .unwrap_or_default(); + let current_validators = + groups.get(current_group_index).map(|v| v.as_slice()).unwrap_or_default(); let validators = &info.discovery_keys; @@ -563,7 +561,7 @@ async fn advertise_collation( let wire_message = protocol_v1::CollatorProtocolMessage::AdvertiseCollation(relay_parent); ctx.send_message(NetworkBridgeTxMessage::SendCollationMessage( - vec![peer.clone()], + vec![peer], Versioned::V1(protocol_v1::CollationProtocol::CollatorProtocol(wire_message)), )) .await; @@ -709,11 +707,8 @@ async fn handle_incoming_peer_message( "AdvertiseCollation message is not expected on the collator side of the protocol", ); - ctx.send_message(NetworkBridgeTxMessage::ReportPeer( - origin.clone(), - COST_UNEXPECTED_MESSAGE, - )) - .await; + ctx.send_message(NetworkBridgeTxMessage::ReportPeer(origin, COST_UNEXPECTED_MESSAGE)) + .await; // If we are advertised to, this is another collator, and we should disconnect. ctx.send_message(NetworkBridgeTxMessage::DisconnectPeer(origin, PeerSet::Collation)) @@ -840,14 +835,14 @@ async fn handle_peer_view_change( peer_id: PeerId, view: View, ) { - let current = state.peer_views.entry(peer_id.clone()).or_default(); + let current = state.peer_views.entry(peer_id).or_default(); let added: Vec = view.difference(&*current).cloned().collect(); *current = view; for added in added.into_iter() { - advertise_collation(ctx, state, added, peer_id.clone()).await; + advertise_collation(ctx, state, added, peer_id).await; } } diff --git a/node/network/collator-protocol/src/collator_side/tests.rs b/node/network/collator-protocol/src/collator_side/tests.rs index c20a2d6c97a5..6575259b37b3 100644 --- a/node/network/collator-protocol/src/collator_side/tests.rs +++ b/node/network/collator-protocol/src/collator_side/tests.rs @@ -44,8 +44,8 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_primitives::v2::{ - AuthorityDiscoveryId, CollatorPair, GroupRotationInfo, ScheduledCore, SessionIndex, - SessionInfo, ValidatorId, ValidatorIndex, + AuthorityDiscoveryId, CollatorPair, GroupIndex, GroupRotationInfo, IndexedVec, ScheduledCore, + SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, }; use polkadot_primitives_test_helpers::TestCandidateBuilder; @@ -62,7 +62,7 @@ struct TestState { session_index: SessionIndex, } -fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec { +fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> IndexedVec { val_ids.iter().map(|v| v.public().into()).collect() } @@ -135,7 +135,7 @@ impl TestState { 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); - &self.session_info.validator_groups[group_idx as usize] + &self.session_info.validator_groups.get(GroupIndex::from(group_idx)).unwrap() } fn current_session_index(&self) -> SessionIndex { @@ -367,7 +367,7 @@ async fn distribute_collation( )) => { assert_eq!(relay_parent, test_state.relay_parent); tx.send(Ok(( - test_state.session_info.validator_groups.clone(), + test_state.session_info.validator_groups.to_vec(), test_state.group_rotation_info.clone(), ))) .unwrap(); diff --git a/node/network/collator-protocol/src/validator_side/mod.rs b/node/network/collator-protocol/src/validator_side/mod.rs index b2b3dc4824b5..1442fbcc2bcb 100644 --- a/node/network/collator-protocol/src/validator_side/mod.rs +++ b/node/network/collator-protocol/src/validator_side/mod.rs @@ -287,7 +287,7 @@ impl PeerData { PeerState::Collating(ref mut state) => if state.advertisements.insert(on_relay_parent) { state.last_active = Instant::now(); - Ok((state.collator_id.clone(), state.para_id.clone())) + Ok((state.collator_id.clone(), state.para_id)) } else { Err(AdvertisementError::Duplicate) }, @@ -375,22 +375,19 @@ impl ActiveParas { .await .await .ok() - .map(|x| x.ok()) - .flatten(); + .and_then(|x| x.ok()); let mg = polkadot_node_subsystem_util::request_validator_groups(relay_parent, sender) .await .await .ok() - .map(|x| x.ok()) - .flatten(); + .and_then(|x| x.ok()); let mc = polkadot_node_subsystem_util::request_availability_cores(relay_parent, sender) .await .await .ok() - .map(|x| x.ok()) - .flatten(); + .and_then(|x| x.ok()); let (validators, groups, rotation_info, cores) = match (mv, mg, mc) { (Some(v), Some((g, r)), Some(c)) => (v, g, r, c), @@ -486,12 +483,7 @@ struct PendingCollation { impl PendingCollation { fn new(relay_parent: Hash, para_id: &ParaId, peer_id: &PeerId) -> Self { - Self { - relay_parent, - para_id: para_id.clone(), - peer_id: peer_id.clone(), - commitments_hash: None, - } + Self { relay_parent, para_id: *para_id, peer_id: *peer_id, commitments_hash: None } } } @@ -629,9 +621,9 @@ fn collator_peer_id( peer_data: &HashMap, collator_id: &CollatorId, ) -> Option { - peer_data.iter().find_map(|(peer, data)| { - data.collator_id().filter(|c| c == &collator_id).map(|_| peer.clone()) - }) + peer_data + .iter() + .find_map(|(peer, data)| data.collator_id().filter(|c| c == &collator_id).map(|_| *peer)) } async fn disconnect_peer(sender: &mut impl overseer::CollatorProtocolSenderTrait, peer_id: PeerId) { @@ -655,9 +647,7 @@ async fn fetch_collation( Delay::new(MAX_UNSHARED_DOWNLOAD_TIME).await; (collator_id, relay_parent) }; - state - .collation_fetch_timeouts - .push(timeout(id.clone(), relay_parent.clone()).boxed()); + state.collation_fetch_timeouts.push(timeout(id.clone(), relay_parent).boxed()); if let Some(peer_data) = state.peer_data.get(&peer_id) { if peer_data.has_advertised(&relay_parent) { @@ -729,7 +719,7 @@ async fn notify_collation_seconded( /// - Ongoing collation requests have to be canceled. /// - Advertisements by this peer that are no longer relevant have to be removed. async fn handle_peer_view_change(state: &mut State, peer_id: PeerId, view: View) -> Result<()> { - let peer_data = state.peer_data.entry(peer_id.clone()).or_default(); + let peer_data = state.peer_data.entry(peer_id).or_default(); peer_data.update_view(view); state @@ -883,7 +873,7 @@ async fn process_incoming_peer_message( "Declared as collator for unneeded para", ); - modify_reputation(ctx.sender(), origin.clone(), COST_UNNEEDED_COLLATOR).await; + modify_reputation(ctx.sender(), origin, COST_UNNEEDED_COLLATOR).await; gum::trace!(target: LOG_TARGET, "Disconnecting unneeded collator"); disconnect_peer(ctx.sender(), origin).await; } @@ -1013,7 +1003,7 @@ async fn handle_our_view_change( .span_per_head() .iter() .filter(|v| !old_view.contains(&v.0)) - .map(|v| (v.0.clone(), v.1.clone())) + .map(|v| (*v.0, v.1.clone())) .collect(); added.into_iter().for_each(|(h, s)| { @@ -1046,7 +1036,7 @@ async fn handle_our_view_change( ?para_id, "Disconnecting peer on view change (not current parachain id)" ); - disconnect_peer(ctx.sender(), peer_id.clone()).await; + disconnect_peer(ctx.sender(), *peer_id).await; } } } @@ -1254,7 +1244,7 @@ async fn poll_requests( retained_requested.insert(pending_collation.clone()); } if let CollationFetchResult::Error(Some(rep)) = result { - reputation_changes.push((pending_collation.peer_id.clone(), rep)); + reputation_changes.push((pending_collation.peer_id, rep)); } } requested_collations.retain(|k, _| retained_requested.contains(k)); @@ -1337,11 +1327,7 @@ async fn handle_collation_fetched_result( if let Entry::Vacant(entry) = state.pending_candidates.entry(relay_parent) { collation_event.1.commitments_hash = Some(candidate_receipt.commitments_hash); ctx.sender() - .send_message(CandidateBackingMessage::Second( - relay_parent.clone(), - candidate_receipt, - pov, - )) + .send_message(CandidateBackingMessage::Second(relay_parent, candidate_receipt, pov)) .await; entry.insert(collation_event); @@ -1366,7 +1352,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"); - disconnect_peer(sender, peer.clone()).await; + disconnect_peer(sender, *peer).await; } } } diff --git a/node/network/dispute-distribution/Cargo.toml b/node/network/dispute-distribution/Cargo.toml index 270d73529334..16ce9548e1c2 100644 --- a/node/network/dispute-distribution/Cargo.toml +++ b/node/network/dispute-distribution/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-dispute-distribution" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -16,9 +16,9 @@ polkadot-node-subsystem = {path = "../../subsystem" } polkadot-node-network-protocol = { path = "../../network/protocol" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } polkadot-node-primitives = { path = "../../primitives" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } thiserror = "1.0.31" fatality = "0.0.6" lru = "0.8.0" @@ -27,9 +27,9 @@ indexmap = "1.9.1" [dev-dependencies] async-trait = "0.1.57" polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures-timer = "3.0.2" assert_matches = "1.4.0" lazy_static = "1.4.0" diff --git a/node/network/dispute-distribution/src/receiver/mod.rs b/node/network/dispute-distribution/src/receiver/mod.rs index 158c66e20655..b84be7b2dfde 100644 --- a/node/network/dispute-distribution/src/receiver/mod.rs +++ b/node/network/dispute-distribution/src/receiver/mod.rs @@ -302,6 +302,12 @@ where // Queue request: if let Err((authority_id, req)) = self.peer_queues.push_req(authority_id, req) { + gum::debug!( + target: LOG_TARGET, + ?authority_id, + ?peer, + "Peer hit the rate limit - dropping message." + ); req.send_outgoing_response(OutgoingResponse { result: Err(()), reputation_changes: vec![COST_APPARENT_FLOOD], @@ -424,7 +430,7 @@ where ); return }, - Some(vote) => (vote.0.session_index(), vote.0.candidate_hash().clone()), + Some(vote) => (vote.0.session_index(), *vote.0.candidate_hash()), }; let (pending_confirmation, confirmation_rx) = oneshot::channel(); diff --git a/node/network/dispute-distribution/src/sender/mod.rs b/node/network/dispute-distribution/src/sender/mod.rs index 09b902173ede..a54033945d6f 100644 --- a/node/network/dispute-distribution/src/sender/mod.rs +++ b/node/network/dispute-distribution/src/sender/mod.rs @@ -108,8 +108,6 @@ impl DisputeSender { runtime: &mut RuntimeInfo, msg: DisputeMessage, ) -> Result<()> { - self.rate_limit.limit().await; - let req: DisputeRequest = msg.into(); let candidate_hash = req.0.candidate_receipt.hash(); match self.disputes.entry(candidate_hash) { @@ -118,6 +116,8 @@ impl DisputeSender { return Ok(()) }, Entry::Vacant(vacant) => { + self.rate_limit.limit("in start_sender", candidate_hash).await; + let send_task = SendTask::new( ctx, runtime, @@ -169,10 +169,12 @@ impl DisputeSender { // Iterates in order of insertion: let mut should_rate_limit = true; - for dispute in self.disputes.values_mut() { + for (candidate_hash, dispute) in self.disputes.iter_mut() { if have_new_sessions || dispute.has_failed_sends() { if should_rate_limit { - self.rate_limit.limit().await; + self.rate_limit + .limit("while going through new sessions/failed sends", *candidate_hash) + .await; } let sends_happened = dispute .refresh_sends(ctx, runtime, &self.active_sessions, &self.metrics) @@ -193,7 +195,7 @@ impl DisputeSender { // recovered at startup will be relatively "old" anyway and we assume that no more than a // third of the validators will go offline at any point in time anyway. for dispute in unknown_disputes { - self.rate_limit.limit().await; + // Rate limiting handled inside `start_send_for_dispute` (calls `start_sender`). self.start_send_for_dispute(ctx, runtime, dispute).await?; } Ok(()) @@ -277,7 +279,7 @@ impl DisputeSender { Some(votes) => votes, }; - let our_valid_vote = votes.valid.get(&our_index); + let our_valid_vote = votes.valid.raw().get(&our_index); let our_invalid_vote = votes.invalid.get(&our_index); @@ -289,7 +291,7 @@ impl DisputeSender { } else if let Some(our_invalid_vote) = our_invalid_vote { // Get some valid vote as well: let valid_vote = - votes.valid.iter().next().ok_or(JfyiError::MissingVotesFromCoordinator)?; + votes.valid.raw().iter().next().ok_or(JfyiError::MissingVotesFromCoordinator)?; (valid_vote, (&our_index, our_invalid_vote)) } else { // There is no vote from us yet - nothing to do. @@ -299,10 +301,10 @@ impl DisputeSender { let valid_public = info .session_info .validators - .get(valid_index.0 as usize) + .get(*valid_index) .ok_or(JfyiError::InvalidStatementFromCoordinator)?; let valid_signed = SignedDisputeStatement::new_checked( - DisputeStatement::Valid(kind.clone()), + DisputeStatement::Valid(*kind), candidate_hash, session_index, valid_public.clone(), @@ -314,10 +316,10 @@ impl DisputeSender { let invalid_public = info .session_info .validators - .get(invalid_index.0 as usize) + .get(*invalid_index) .ok_or(JfyiError::InvalidValidatorIndexFromCoordinator)?; let invalid_signed = SignedDisputeStatement::new_checked( - DisputeStatement::Invalid(kind.clone()), + DisputeStatement::Invalid(*kind), candidate_hash, session_index, invalid_public.clone(), @@ -383,16 +385,23 @@ impl RateLimit { } /// Wait until ready and prepare for next call. - async fn limit(&mut self) { + /// + /// String given as occasion and candidate hash are logged in case the rate limit hit. + async fn limit(&mut self, occasion: &'static str, candidate_hash: CandidateHash) { // Wait for rate limit and add some logging: + let mut num_wakes: u32 = 0; poll_fn(|cx| { let old_limit = Pin::new(&mut self.limit); match old_limit.poll(cx) { Poll::Pending => { gum::debug!( target: LOG_TARGET, + ?occasion, + ?candidate_hash, + ?num_wakes, "Sending rate limit hit, slowing down requests" ); + num_wakes += 1; Poll::Pending }, Poll::Ready(()) => Poll::Ready(()), @@ -430,7 +439,9 @@ async fn get_active_disputes( // Caller scope is in `update_leaves` and this is bounded by fork count. ctx.send_unbounded_message(DisputeCoordinatorMessage::ActiveDisputes(tx)); - rx.await.map_err(|_| JfyiError::AskActiveDisputesCanceled) + rx.await + .map_err(|_| JfyiError::AskActiveDisputesCanceled) + .map(|disputes| disputes.into_iter().map(|d| (d.0, d.1)).collect()) } /// Get all locally available dispute votes for a given dispute. diff --git a/node/network/dispute-distribution/src/sender/send_task.rs b/node/network/dispute-distribution/src/sender/send_task.rs index 89b5c099bde9..3852adbc141b 100644 --- a/node/network/dispute-distribution/src/sender/send_task.rs +++ b/node/network/dispute-distribution/src/sender/send_task.rs @@ -140,21 +140,38 @@ impl SendTask { let new_authorities = self.get_relevant_validators(ctx, runtime, active_sessions).await?; // Note this will also contain all authorities for which sending failed previously: - let add_authorities = new_authorities + let add_authorities: Vec<_> = new_authorities .iter() .filter(|a| !self.deliveries.contains_key(a)) .map(Clone::clone) .collect(); // Get rid of dead/irrelevant tasks/statuses: + gum::trace!( + target: LOG_TARGET, + already_running_deliveries = ?self.deliveries.len(), + "Cleaning up deliveries" + ); self.deliveries.retain(|k, _| new_authorities.contains(k)); // Start any new tasks that are needed: + gum::trace!( + target: LOG_TARGET, + new_and_failed_authorities = ?add_authorities.len(), + overall_authority_set_size = ?new_authorities.len(), + already_running_deliveries = ?self.deliveries.len(), + "Starting new send requests for authorities." + ); let new_statuses = send_requests(ctx, self.tx.clone(), add_authorities, self.request.clone(), metrics) .await?; let was_empty = new_statuses.is_empty(); + gum::trace!( + target: LOG_TARGET, + sent_requests = ?new_statuses.len(), + "Requests dispatched." + ); self.has_failed_sends = false; self.deliveries.extend(new_statuses.into_iter()); diff --git a/node/network/dispute-distribution/src/tests/mock.rs b/node/network/dispute-distribution/src/tests/mock.rs index aa2a4485d480..bc64734d57a0 100644 --- a/node/network/dispute-distribution/src/tests/mock.rs +++ b/node/network/dispute-distribution/src/tests/mock.rs @@ -84,7 +84,7 @@ pub static ref MOCK_SESSION_INFO: SessionInfo = .map(|k| MOCK_VALIDATORS_DISCOVERY_KEYS.get(&k).unwrap().clone()) .collect(), assignment_keys: vec![], - validator_groups: vec![], + validator_groups: Default::default(), n_cores: 0, zeroth_delay_tranche_width: 0, relay_vrf_modulo_samples: 0, @@ -104,9 +104,9 @@ pub static ref MOCK_NEXT_SESSION_INFO: SessionInfo = .iter() .map(|k| MOCK_VALIDATORS_DISCOVERY_KEYS.get(&k).unwrap().clone()) .collect(), - validators: vec![], + validators: Default::default(), assignment_keys: vec![], - validator_groups: vec![], + validator_groups: Default::default(), n_cores: 0, zeroth_delay_tranche_width: 0, relay_vrf_modulo_samples: 0, diff --git a/node/network/dispute-distribution/src/tests/mod.rs b/node/network/dispute-distribution/src/tests/mod.rs index 56cdd467fd62..d6381239965b 100644 --- a/node/network/dispute-distribution/src/tests/mod.rs +++ b/node/network/dispute-distribution/src/tests/mod.rs @@ -45,7 +45,7 @@ use polkadot_node_network_protocol::{ request_response::{v1::DisputeResponse, Recipient, Requests}, IfDisconnected, }; -use polkadot_node_primitives::{CandidateVotes, UncheckedDisputeMessage}; +use polkadot_node_primitives::{CandidateVotes, DisputeStatus, UncheckedDisputeMessage}; use polkadot_node_subsystem::{ messages::{ AllMessages, DisputeCoordinatorMessage, DisputeDistributionMessage, ImportStatementsResult, @@ -658,7 +658,7 @@ fn dispute_retries_and_works_across_session_boundaries() { Some(old_head), MOCK_SESSION_INDEX, None, - vec![(MOCK_SESSION_INDEX, candidate.hash())], + vec![(MOCK_SESSION_INDEX, candidate.hash(), DisputeStatus::Active)], ) .await; @@ -673,7 +673,7 @@ fn dispute_retries_and_works_across_session_boundaries() { Some(old_head2), MOCK_NEXT_SESSION_INDEX, Some(MOCK_NEXT_SESSION_INFO.clone()), - vec![(MOCK_SESSION_INDEX, candidate.hash())], + vec![(MOCK_SESSION_INDEX, candidate.hash(), DisputeStatus::Active)], ) .await; @@ -832,7 +832,7 @@ async fn activate_leaf( // New session if we expect the subsystem to request it. new_session: Option, // Currently active disputes to send to the subsystem. - active_disputes: Vec<(SessionIndex, CandidateHash)>, + active_disputes: Vec<(SessionIndex, CandidateHash, DisputeStatus)>, ) { let has_active_disputes = !active_disputes.is_empty(); handle @@ -934,7 +934,10 @@ async fn handle_subsystem_startup( None, MOCK_SESSION_INDEX, Some(MOCK_SESSION_INFO.clone()), - ongoing_dispute.into_iter().map(|c| (MOCK_SESSION_INDEX, c)).collect(), + ongoing_dispute + .into_iter() + .map(|c| (MOCK_SESSION_INDEX, c, DisputeStatus::Active)) + .collect(), ) .await; relay_parent diff --git a/node/network/gossip-support/Cargo.toml b/node/network/gossip-support/Cargo.toml index d8c8a633cab3..cbd11c5f1363 100644 --- a/node/network/gossip-support/Cargo.toml +++ b/node/network/gossip-support/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "polkadot-gossip-support" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-node-network-protocol = { path = "../protocol" } polkadot-node-subsystem = { path = "../../subsystem" } @@ -22,10 +22,10 @@ rand_chacha = { version = "0.3.1", default-features = false } gum = { package = "tracing-gum", path = "../../gum" } [dev-dependencies] -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } diff --git a/node/network/gossip-support/src/tests.rs b/node/network/gossip-support/src/tests.rs index 79f2a9a6db42..4b2b91f7cdba 100644 --- a/node/network/gossip-support/src/tests.rs +++ b/node/network/gossip-support/src/tests.rs @@ -37,6 +37,7 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::TimeoutExt as _; +use polkadot_primitives::v2::{GroupIndex, IndexedVec}; use test_helpers::mock::make_ferdie_keystore; use super::*; @@ -219,7 +220,9 @@ fn make_session_info() -> SessionInfo { validators: AUTHORITY_KEYRINGS.iter().map(|k| k.public().into()).collect(), discovery_keys: AUTHORITIES.clone(), assignment_keys: AUTHORITY_KEYRINGS.iter().map(|k| k.public().into()).collect(), - validator_groups: vec![all_validator_indices], + validator_groups: IndexedVec::>::from(vec![ + all_validator_indices, + ]), n_cores: 1, zeroth_delay_tranche_width: 1, relay_vrf_modulo_samples: 1, diff --git a/node/network/protocol/Cargo.toml b/node/network/protocol/Cargo.toml index 85c9cf2bd86c..f04c913b0608 100644 --- a/node/network/protocol/Cargo.toml +++ b/node/network/protocol/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-node-network-protocol" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true description = "Primitives types for the Node-side" [dependencies] @@ -12,9 +12,9 @@ polkadot-primitives = { path = "../../../primitives" } polkadot-node-primitives = { path = "../../primitives" } polkadot-node-jaeger = { path = "../../jaeger" } parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } strum = { version = "0.24", features = ["derive"] } futures = "0.3.21" thiserror = "1.0.31" diff --git a/node/network/protocol/src/grid_topology.rs b/node/network/protocol/src/grid_topology.rs index 100ef66957bd..2ae43c07c355 100644 --- a/node/network/protocol/src/grid_topology.rs +++ b/node/network/protocol/src/grid_topology.rs @@ -94,7 +94,7 @@ impl SessionGridTopology { let n = &self.canonical_shuffling[r_n]; grid_subset.validator_indices_x.insert(n.validator_index); for p in &n.peer_ids { - grid_subset.peers_x.insert(p.clone()); + grid_subset.peers_x.insert(*p); } } @@ -102,7 +102,7 @@ impl SessionGridTopology { let n = &self.canonical_shuffling[c_n]; grid_subset.validator_indices_y.insert(n.validator_index); for p in &n.peer_ids { - grid_subset.peers_y.insert(p.clone()); + grid_subset.peers_y.insert(*p); } } diff --git a/node/network/protocol/src/lib.rs b/node/network/protocol/src/lib.rs index 169d916ce6f9..744217133eed 100644 --- a/node/network/protocol/src/lib.rs +++ b/node/network/protocol/src/lib.rs @@ -207,7 +207,7 @@ impl View { } /// Obtain an iterator over all heads. - pub fn iter<'a>(&'a self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.heads.iter() } diff --git a/node/network/protocol/src/peer_set.rs b/node/network/protocol/src/peer_set.rs index d9d2925e594d..22eddc44c42f 100644 --- a/node/network/protocol/src/peer_set.rs +++ b/node/network/protocol/src/peer_set.rs @@ -36,7 +36,7 @@ const LEGACY_COLLATION_PROTOCOL_V1: &str = "/polkadot/collation/1"; const LEGACY_PROTOCOL_VERSION_V1: u32 = 1; /// Max notification size is currently constant. -const MAX_NOTIFICATION_SIZE: u64 = 100 * 1024; +pub const MAX_NOTIFICATION_SIZE: u64 = 100 * 1024; /// The peer-sets and thus the protocols which are used for the network. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)] diff --git a/node/network/protocol/src/request_response/mod.rs b/node/network/protocol/src/request_response/mod.rs index d24537e219c7..6ce0c883cc6c 100644 --- a/node/network/protocol/src/request_response/mod.rs +++ b/node/network/protocol/src/request_response/mod.rs @@ -126,6 +126,17 @@ const STATEMENT_RESPONSE_SIZE: u64 = MAX_CODE_SIZE as u64 + 10_000; pub const DISPUTE_REQUEST_TIMEOUT: Duration = Duration::from_secs(12); impl Protocol { + /// Get a configuration for a given Request response protocol. + /// + /// Returns a `ProtocolConfig` for this protocol. + /// Use this if you plan only to send requests for this protocol. + pub fn get_outbound_only_config( + self, + req_protocol_names: &ReqProtocolNames, + ) -> RequestResponseConfig { + self.create_config(req_protocol_names, None) + } + /// Get a configuration for a given Request response protocol. /// /// Returns a receiver for messages received on this protocol and the requested @@ -134,10 +145,19 @@ impl Protocol { self, req_protocol_names: &ReqProtocolNames, ) -> (mpsc::Receiver, RequestResponseConfig) { + let (tx, rx) = mpsc::channel(self.get_channel_size()); + let cfg = self.create_config(req_protocol_names, Some(tx)); + (rx, cfg) + } + + fn create_config( + self, + req_protocol_names: &ReqProtocolNames, + tx: Option>, + ) -> RequestResponseConfig { let name = req_protocol_names.get_name(self); let fallback_names = self.get_fallback_names(); - let (tx, rx) = mpsc::channel(self.get_channel_size()); - let cfg = match self { + match self { Protocol::ChunkFetchingV1 => RequestResponseConfig { name, fallback_names, @@ -145,7 +165,7 @@ impl Protocol { max_response_size: POV_RESPONSE_SIZE as u64 * 3, // We are connected to all validators: request_timeout: CHUNK_REQUEST_TIMEOUT, - inbound_queue: Some(tx), + inbound_queue: tx, }, Protocol::CollationFetchingV1 => RequestResponseConfig { name, @@ -154,7 +174,7 @@ impl Protocol { max_response_size: POV_RESPONSE_SIZE, // Taken from initial implementation in collator protocol: request_timeout: POV_REQUEST_TIMEOUT_CONNECTED, - inbound_queue: Some(tx), + inbound_queue: tx, }, Protocol::PoVFetchingV1 => RequestResponseConfig { name, @@ -162,7 +182,7 @@ impl Protocol { max_request_size: 1_000, max_response_size: POV_RESPONSE_SIZE, request_timeout: POV_REQUEST_TIMEOUT_CONNECTED, - inbound_queue: Some(tx), + inbound_queue: tx, }, Protocol::AvailableDataFetchingV1 => RequestResponseConfig { name, @@ -171,7 +191,7 @@ impl Protocol { // Available data size is dominated by the PoV size. max_response_size: POV_RESPONSE_SIZE, request_timeout: POV_REQUEST_TIMEOUT_CONNECTED, - inbound_queue: Some(tx), + inbound_queue: tx, }, Protocol::StatementFetchingV1 => RequestResponseConfig { name, @@ -189,7 +209,7 @@ impl Protocol { // fail, but this is desired, so we can quickly move on to a faster one - we should // also decrease its reputation. request_timeout: Duration::from_secs(1), - inbound_queue: Some(tx), + inbound_queue: tx, }, Protocol::DisputeSendingV1 => RequestResponseConfig { name, @@ -199,10 +219,9 @@ impl Protocol { /// plenty. max_response_size: 100, request_timeout: DISPUTE_REQUEST_TIMEOUT, - inbound_queue: Some(tx), + inbound_queue: tx, }, - }; - (rx, cfg) + } } // Channel sizes for the supported protocols. diff --git a/node/network/statement-distribution/Cargo.toml b/node/network/statement-distribution/Cargo.toml index a0e06b357cbe..9fdf2e6823ef 100644 --- a/node/network/statement-distribution/Cargo.toml +++ b/node/network/statement-distribution/Cargo.toml @@ -1,16 +1,16 @@ [package] name = "polkadot-statement-distribution" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Statement Distribution Subsystem" -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" gum = { package = "tracing-gum", path = "../../gum" } polkadot-primitives = { path = "../../../primitives" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-node-subsystem = {path = "../../subsystem" } polkadot-node-primitives = { path = "../../primitives" } polkadot-node-subsystem-util = { path = "../../subsystem-util" } @@ -24,13 +24,13 @@ fatality = "0.0.6" [dev-dependencies] polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" } assert_matches = "1.4.0" -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures-timer = "3.0.2" polkadot-primitives-test-helpers = { path = "../../../primitives/test-helpers" } diff --git a/node/network/statement-distribution/src/lib.rs b/node/network/statement-distribution/src/lib.rs index 17ca5d8ea4ac..271072ab1031 100644 --- a/node/network/statement-distribution/src/lib.rs +++ b/node/network/statement-distribution/src/lib.rs @@ -47,8 +47,8 @@ use polkadot_node_subsystem::{ }; use polkadot_primitives::v2::{ AuthorityDiscoveryId, CandidateHash, CommittedCandidateReceipt, CompactStatement, Hash, - SignedStatement, SigningContext, UncheckedSignedStatement, ValidatorId, ValidatorIndex, - ValidatorSignature, + IndexedVec, SignedStatement, SigningContext, UncheckedSignedStatement, ValidatorId, + ValidatorIndex, ValidatorSignature, }; use futures::{ @@ -278,10 +278,10 @@ impl PeerRelayParentKnowledge { let new_known = match fingerprint.0 { CompactStatement::Seconded(ref h) => { - self.seconded_counts.entry(fingerprint.1).or_default().note_local(h.clone()); + self.seconded_counts.entry(fingerprint.1).or_default().note_local(*h); let was_known = self.is_known_candidate(h); - self.sent_candidates.insert(h.clone()); + self.sent_candidates.insert(*h); !was_known }, CompactStatement::Valid(_) => false, @@ -345,7 +345,7 @@ impl PeerRelayParentKnowledge { .seconded_counts .entry(fingerprint.1) .or_insert_with(Default::default) - .note_remote(h.clone()); + .note_remote(*h); if !allowed_remote { return Err(COST_UNEXPECTED_STATEMENT_REMOTE) @@ -374,7 +374,7 @@ impl PeerRelayParentKnowledge { } self.received_statements.insert(fingerprint.clone()); - self.received_candidates.insert(candidate_hash.clone()); + self.received_candidates.insert(*candidate_hash); Ok(fresh) } @@ -665,7 +665,7 @@ struct ActiveHeadData { /// Large statements we are waiting for with associated meta data. waiting_large_statements: HashMap, /// The parachain validators at the head's child session index. - validators: Vec, + validators: IndexedVec, /// The current session index of this fork. session_index: sp_staking::SessionIndex, /// How many `Seconded` statements we've seen per validator. @@ -676,7 +676,7 @@ struct ActiveHeadData { impl ActiveHeadData { fn new( - validators: Vec, + validators: IndexedVec, session_index: sp_staking::SessionIndex, span: PerLeafSpan, ) -> Self { @@ -878,7 +878,7 @@ fn check_statement_signature( SigningContext { session_index: head.session_index, parent_hash: relay_parent }; head.validators - .get(statement.unchecked_validator_index().0 as usize) + .get(statement.unchecked_validator_index()) .ok_or_else(|| statement.clone()) .and_then(|v| statement.try_into_checked(&signing_context, v)) } @@ -1025,13 +1025,15 @@ async fn circulate_statement<'a, Context>( let mut peers_to_send: Vec = peers .iter() - .filter_map(|(peer, data)| { - if data.can_send(&relay_parent, &fingerprint) { - Some(peer.clone()) - } else { - None - } - }) + .filter_map( + |(peer, data)| { + if data.can_send(&relay_parent, &fingerprint) { + Some(*peer) + } else { + None + } + }, + ) .collect(); let good_peers: HashSet<&PeerId> = peers_to_send.iter().collect(); @@ -1087,7 +1089,7 @@ async fn circulate_statement<'a, Context>( "Sending statement", ); ctx.send_message(NetworkBridgeTxMessage::SendValidationMessage( - peers_to_send.iter().map(|(p, _)| p.clone()).collect(), + peers_to_send.iter().map(|(p, _)| *p).collect(), payload, )) .await; @@ -1126,11 +1128,8 @@ async fn send_statements_about( statement = ?statement.statement, "Sending statement", ); - ctx.send_message(NetworkBridgeTxMessage::SendValidationMessage( - vec![peer.clone()], - payload, - )) - .await; + ctx.send_message(NetworkBridgeTxMessage::SendValidationMessage(vec![peer], payload)) + .await; metrics.on_statement_distributed(); } @@ -1161,11 +1160,8 @@ async fn send_statements( statement = ?statement.statement, "Sending statement" ); - ctx.send_message(NetworkBridgeTxMessage::SendValidationMessage( - vec![peer.clone()], - payload, - )) - .await; + ctx.send_message(NetworkBridgeTxMessage::SendValidationMessage(vec![peer], payload)) + .await; metrics.on_statement_distributed(); } @@ -1431,7 +1427,7 @@ async fn handle_incoming_message<'a, Context>( } let fingerprint = message.get_fingerprint(); - let candidate_hash = fingerprint.0.candidate_hash().clone(); + let candidate_hash = *fingerprint.0.candidate_hash(); let handle_incoming_span = active_head .span .child("handle-incoming") @@ -1551,7 +1547,7 @@ async fn handle_incoming_message<'a, Context>( // Send the peer all statements concerning the candidate that we have, // since it appears to have just learned about the candidate. send_statements_about( - peer.clone(), + peer, peer_data, ctx, relay_parent, @@ -1627,7 +1623,7 @@ async fn update_peer_view_and_maybe_send_unlocked( continue } if let Some(active_head) = active_heads.get(&new) { - send_statements(peer.clone(), peer_data, ctx, new, active_head, metrics).await; + send_statements(peer, peer_data, ctx, new, active_head, metrics).await; } } } @@ -1710,7 +1706,7 @@ async fn handle_network_update( topology_storage, peers, active_heads, - &*recent_outdated_heads, + recent_outdated_heads, ctx, message, req_sender, @@ -2017,7 +2013,7 @@ impl StatementDistributionSubsystem { } } - for activated in activated { + if let Some(activated) = activated { let relay_parent = activated.hash; let span = PerLeafSpan::new(activated.span, "statement-distribution"); gum::trace!( @@ -2072,7 +2068,10 @@ impl StatementDistributionSubsystem { // directly: let group_peers = { if let Some(our_group) = validator_info.our_group { - let our_group = &session_info.validator_groups[our_group.0 as usize]; + let our_group = &session_info + .validator_groups + .get(our_group) + .expect("`our_group` is derived from `validator_groups`; qed"); our_group .into_iter() diff --git a/node/network/statement-distribution/src/metrics.rs b/node/network/statement-distribution/src/metrics.rs index 6bc6f724ae09..6acbf63eadc0 100644 --- a/node/network/statement-distribution/src/metrics.rs +++ b/node/network/statement-distribution/src/metrics.rs @@ -17,8 +17,10 @@ use polkadot_node_subsystem_util::metrics::{self, prometheus}; /// Buckets more suitable for checking the typical latency values -const HISTOGRAM_LATENCY_BUCKETS: &[f64] = - &[0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.75, 0.9, 1.0, 1.2, 1.5, 1.75]; +const HISTOGRAM_LATENCY_BUCKETS: &[f64] = &[ + 0.000025, 0.00005, 0.000075, 0.0001, 0.0003125, 0.000625, 0.00125, 0.0025, 0.005, 0.01, 0.025, + 0.05, 0.1, +]; #[derive(Clone)] struct MetricsInner { diff --git a/node/network/statement-distribution/src/tests.rs b/node/network/statement-distribution/src/tests.rs index f3b9db00aef4..c1636557fdca 100644 --- a/node/network/statement-distribution/src/tests.rs +++ b/node/network/statement-distribution/src/tests.rs @@ -35,7 +35,9 @@ use polkadot_node_subsystem::{ ActivatedLeaf, LeafStatus, }; use polkadot_node_subsystem_test_helpers::mock::make_ferdie_keystore; -use polkadot_primitives::v2::{Hash, Id as ParaId, SessionInfo, ValidationCode}; +use polkadot_primitives::v2::{ + GroupIndex, Hash, Id as ParaId, IndexedVec, SessionInfo, ValidationCode, ValidatorId, +}; use polkadot_primitives_test_helpers::{ dummy_committed_candidate_receipt, dummy_hash, AlwaysZeroRng, }; @@ -83,7 +85,7 @@ fn active_head_accepts_only_2_seconded_per_validator() { }; let mut head_data = ActiveHeadData::new( - validators, + IndexedVec::::from(validators), session_index, PerLeafSpan::new(Arc::new(jaeger::Span::Disabled), "test"), ); @@ -429,7 +431,7 @@ fn peer_view_update_sends_messages() { let new_head_data = { let mut data = ActiveHeadData::new( - validators, + IndexedVec::::from(validators), session_index, PerLeafSpan::new(Arc::new(jaeger::Span::Disabled), "test"), ); @@ -2319,7 +2321,7 @@ fn handle_multiple_seconded_statements() { } fn make_session_info(validators: Vec, groups: Vec>) -> SessionInfo { - let validator_groups: Vec> = groups + let validator_groups: IndexedVec> = groups .iter() .map(|g| g.into_iter().map(|v| ValidatorIndex(*v)).collect()) .collect(); diff --git a/node/overseer/Cargo.toml b/node/overseer/Cargo.toml index eb02b2cc1c6d..00324f05b28d 100644 --- a/node/overseer/Cargo.toml +++ b/node/overseer/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "polkadot-overseer" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] -client = { package = "sc-client-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +client = { package = "sc-client-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures = "0.3.21" futures-timer = "3.0.2" parking_lot = "0.12.0" @@ -18,14 +18,14 @@ polkadot-primitives = { path = "../../primitives" } orchestra = "0.0.2" gum = { package = "tracing-gum", path = "../gum" } lru = "0.8" -parity-util-mem = { version = "0.12.0", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } async-trait = "0.1.57" +tikv-jemalloc-ctl = "0.5.0" [dev-dependencies] metered = { package = "prioritized-metered-channel", version = "0.2.0" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures = { version = "0.3.21", features = ["thread-pool"] } femme = "2.2.1" assert_matches = "1.4.0" diff --git a/node/overseer/src/dummy.rs b/node/overseer/src/dummy.rs index 84ecdd1e8a89..0706244356aa 100644 --- a/node/overseer/src/dummy.rs +++ b/node/overseer/src/dummy.rs @@ -56,10 +56,10 @@ where /// Create an overseer with all subsystem being `Sub`. /// /// Preferred way of initializing a dummy overseer for subsystem tests. -pub fn dummy_overseer_builder<'a, Spawner, SupportsParachains>( +pub fn dummy_overseer_builder( spawner: Spawner, supports_parachains: SupportsParachains, - registry: Option<&'a Registry>, + registry: Option<&Registry>, ) -> Result< InitializedOverseerBuilder< SpawnGlue, @@ -97,11 +97,11 @@ where } /// Create an overseer with all subsystem being `Sub`. -pub fn one_for_all_overseer_builder<'a, Spawner, SupportsParachains, Sub>( +pub fn one_for_all_overseer_builder( spawner: Spawner, supports_parachains: SupportsParachains, subsystem: Sub, - registry: Option<&'a Registry>, + registry: Option<&Registry>, ) -> Result< InitializedOverseerBuilder< SpawnGlue, diff --git a/node/overseer/src/lib.rs b/node/overseer/src/lib.rs index 70dbe92b2432..78d1e1fe7889 100644 --- a/node/overseer/src/lib.rs +++ b/node/overseer/src/lib.rs @@ -101,8 +101,6 @@ pub use polkadot_node_metrics::{ Metronome, }; -use parity_util_mem::MemoryAllocationTracker; - pub use orchestra as gen; pub use orchestra::{ contextbounds, orchestra, subsystem, FromOrchestra, MapSubsystem, MessagePacket, @@ -118,11 +116,14 @@ pub const KNOWN_LEAVES_CACHE_SIZE: NonZeroUsize = match NonZeroUsize::new(2 * 24 None => panic!("Known leaves cache size must be non-zero"), }; +mod memory_stats; #[cfg(test)] mod tests; use sp_core::traits::SpawnNamed; +use memory_stats::MemoryAllocationTracker; + /// Glue to connect `trait orchestra::Spawner` and `SpawnNamed` from `substrate`. pub struct SpawnGlue(pub S); @@ -686,7 +687,7 @@ where subsystem_meters .iter() .cloned() - .filter_map(|x| x) + .flatten() .map(|(name, ref meters)| (name, meters.read())), ); @@ -861,7 +862,7 @@ where let mut span = jaeger::Span::new(*hash, "leaf-activated"); if let Some(parent_span) = parent_hash.and_then(|h| self.span_per_active_leaf.get(&h)) { - span.add_follows_from(&*parent_span); + span.add_follows_from(parent_span); } let span = Arc::new(span); diff --git a/node/overseer/src/memory_stats.rs b/node/overseer/src/memory_stats.rs new file mode 100644 index 000000000000..670762a4935c --- /dev/null +++ b/node/overseer/src/memory_stats.rs @@ -0,0 +1,53 @@ +// Copyright 2017-2022 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 tikv_jemalloc_ctl::{epoch, stats, Error}; + +#[derive(Clone)] +pub struct MemoryAllocationTracker { + epoch: tikv_jemalloc_ctl::epoch_mib, + allocated: stats::allocated_mib, + resident: stats::resident_mib, +} + +impl MemoryAllocationTracker { + pub fn new() -> Result { + Ok(Self { + epoch: epoch::mib()?, + allocated: stats::allocated::mib()?, + resident: stats::resident::mib()?, + }) + } + + pub fn snapshot(&self) -> Result { + // update stats by advancing the allocation epoch + self.epoch.advance()?; + + let allocated: u64 = self.allocated.read()? as _; + let resident: u64 = self.resident.read()? as _; + Ok(MemoryAllocationSnapshot { allocated, resident }) + } +} + +/// Snapshot of collected memory metrics. +#[non_exhaustive] +#[derive(Debug, Clone)] +pub struct MemoryAllocationSnapshot { + /// Total resident memory, in bytes. + pub resident: u64, + /// Total allocated memory, in bytes. + pub allocated: u64, +} diff --git a/node/overseer/src/metrics.rs b/node/overseer/src/metrics.rs index 71295dd2238c..bb7d98a68f2e 100644 --- a/node/overseer/src/metrics.rs +++ b/node/overseer/src/metrics.rs @@ -19,7 +19,7 @@ use super::*; pub use polkadot_node_metrics::metrics::{self, prometheus, Metrics as MetricsTrait}; -use parity_util_mem::MemoryAllocationSnapshot; +use memory_stats::MemoryAllocationSnapshot; /// Overseer Prometheus metrics. #[derive(Clone)] diff --git a/node/primitives/Cargo.toml b/node/primitives/Cargo.toml index 137231f4272b..f139b261df3f 100644 --- a/node/primitives/Cargo.toml +++ b/node/primitives/Cargo.toml @@ -1,21 +1,21 @@ [package] name = "polkadot-node-primitives" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" description = "Primitives types for the Node-side" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] bounded-vec = "0.6" futures = "0.3.21" polkadot-primitives = { path = "../../primitives" } parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus-vrf = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus-vrf = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-maybe-compressed-blob = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-parachain = { path = "../../parachain", default-features = false } schnorrkel = "0.9.1" thiserror = "1.0.31" diff --git a/node/primitives/src/disputes/message.rs b/node/primitives/src/disputes/message.rs index 88a65ab04015..c31ff1ecb283 100644 --- a/node/primitives/src/disputes/message.rs +++ b/node/primitives/src/disputes/message.rs @@ -33,6 +33,9 @@ use polkadot_primitives::v2::{ /// /// And most likely has been constructed correctly. This is used with /// `DisputeDistributionMessage::SendDispute` for sending out votes. +/// +/// NOTE: This is sent over the wire, any changes are a change in protocol and need to be +/// versioned. #[derive(Debug, Clone)] pub struct DisputeMessage(UncheckedDisputeMessage); @@ -135,11 +138,11 @@ impl DisputeMessage { let valid_id = session_info .validators - .get(valid_index.0 as usize) + .get(valid_index) .ok_or(Error::ValidStatementInvalidValidatorIndex)?; let invalid_id = session_info .validators - .get(invalid_index.0 as usize) + .get(invalid_index) .ok_or(Error::InvalidStatementInvalidValidatorIndex)?; if valid_id != valid_statement.validator_public() { @@ -167,13 +170,13 @@ impl DisputeMessage { let valid_vote = ValidDisputeVote { validator_index: valid_index, signature: valid_statement.validator_signature().clone(), - kind: valid_kind.clone(), + kind: *valid_kind, }; let invalid_vote = InvalidDisputeVote { validator_index: invalid_index, signature: invalid_statement.validator_signature().clone(), - kind: invalid_kind.clone(), + kind: *invalid_kind, }; Ok(DisputeMessage(UncheckedDisputeMessage { @@ -223,8 +226,7 @@ impl UncheckedDisputeMessage { let vote_valid = { let ValidDisputeVote { validator_index, signature, kind } = valid_vote; - let validator_public = - session_info.validators.get(validator_index.0 as usize).ok_or(())?.clone(); + let validator_public = session_info.validators.get(validator_index).ok_or(())?.clone(); ( SignedDisputeStatement::new_checked( @@ -240,8 +242,7 @@ impl UncheckedDisputeMessage { let vote_invalid = { let InvalidDisputeVote { validator_index, signature, kind } = invalid_vote; - let validator_public = - session_info.validators.get(validator_index.0 as usize).ok_or(())?.clone(); + let validator_public = session_info.validators.get(validator_index).ok_or(())?.clone(); ( SignedDisputeStatement::new_checked( diff --git a/node/primitives/src/disputes/mod.rs b/node/primitives/src/disputes/mod.rs index ee047c7bcc22..bad2ddbffc46 100644 --- a/node/primitives/src/disputes/mod.rs +++ b/node/primitives/src/disputes/mod.rs @@ -14,7 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::{ + btree_map::{Entry as Bentry, Keys as Bkeys}, + BTreeMap, BTreeSet, +}; use parity_scale_codec::{Decode, Encode}; @@ -49,7 +52,7 @@ pub struct CandidateVotes { /// The receipt of the candidate itself. pub candidate_receipt: CandidateReceipt, /// Votes of validity, sorted by validator index. - pub valid: BTreeMap, + pub valid: ValidCandidateVotes, /// Votes of invalidity, sorted by validator index. pub invalid: BTreeMap, } @@ -69,6 +72,99 @@ impl CandidateVotes { } } +#[derive(Debug, Clone)] +/// Valid candidate votes. +/// +/// Prefere backing votes over other votes. +pub struct ValidCandidateVotes { + votes: BTreeMap, +} + +impl ValidCandidateVotes { + /// Create new empty `ValidCandidateVotes` + pub fn new() -> Self { + Self { votes: BTreeMap::new() } + } + /// Insert a vote, replacing any already existing vote. + /// + /// Except, for backing votes: Backing votes are always kept, and will never get overridden. + /// Import of other king of `valid` votes, will be ignored if a backing vote is already + /// present. Any already existing `valid` vote, will be overridden by any given backing vote. + /// + /// Returns: true, if the insert had any effect. + pub fn insert_vote( + &mut self, + validator_index: ValidatorIndex, + kind: ValidDisputeStatementKind, + sig: ValidatorSignature, + ) -> bool { + match self.votes.entry(validator_index) { + Bentry::Vacant(vacant) => { + vacant.insert((kind, sig)); + true + }, + Bentry::Occupied(mut occupied) => match occupied.get().0 { + ValidDisputeStatementKind::BackingValid(_) | + ValidDisputeStatementKind::BackingSeconded(_) => false, + ValidDisputeStatementKind::Explicit | + ValidDisputeStatementKind::ApprovalChecking => { + occupied.insert((kind, sig)); + kind != occupied.get().0 + }, + }, + } + } + + /// Retain any votes that match the given criteria. + pub fn retain(&mut self, f: F) + where + F: FnMut(&ValidatorIndex, &mut (ValidDisputeStatementKind, ValidatorSignature)) -> bool, + { + self.votes.retain(f) + } + + /// Get all the validator indeces we have votes for. + pub fn keys( + &self, + ) -> Bkeys<'_, ValidatorIndex, (ValidDisputeStatementKind, ValidatorSignature)> { + self.votes.keys() + } + + /// Get read only direct access to underlying map. + pub fn raw( + &self, + ) -> &BTreeMap { + &self.votes + } +} + +impl FromIterator<(ValidatorIndex, (ValidDisputeStatementKind, ValidatorSignature))> + for ValidCandidateVotes +{ + fn from_iter(iter: T) -> Self + where + T: IntoIterator, + { + Self { votes: BTreeMap::from_iter(iter) } + } +} + +impl From + for BTreeMap +{ + fn from(wrapped: ValidCandidateVotes) -> Self { + wrapped.votes + } +} +impl IntoIterator for ValidCandidateVotes { + type Item = (ValidatorIndex, (ValidDisputeStatementKind, ValidatorSignature)); + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.votes.into_iter() + } +} + impl SignedDisputeStatement { /// Create a new `SignedDisputeStatement` from information /// that is available on-chain, and hence already can be trusted. diff --git a/node/primitives/src/disputes/status.rs b/node/primitives/src/disputes/status.rs index c0ffb907423b..7cc26c1a1f7a 100644 --- a/node/primitives/src/disputes/status.rs +++ b/node/primitives/src/disputes/status.rs @@ -19,8 +19,12 @@ use parity_scale_codec::{Decode, Encode}; /// Timestamp based on the 1 Jan 1970 UNIX base, which is persistent across node restarts and OS reboots. pub type Timestamp = u64; -/// The status of dispute. This is a state machine which can be altered by the -/// helper methods. +/// The status of dispute. +/// +/// As managed by the dispute coordinator. +/// +/// NOTE: This status is persisted to the database, any changes have to be versioned and a db +/// migration will be needed. #[derive(Debug, Clone, Copy, Encode, Decode, PartialEq)] pub enum DisputeStatus { /// The dispute is active and unconcluded. @@ -69,9 +73,24 @@ impl DisputeStatus { } } + /// Concluded valid? + pub fn has_concluded_for(&self) -> bool { + match self { + &DisputeStatus::ConcludedFor(_) => true, + _ => false, + } + } + /// Concluded invalid? + pub fn has_concluded_against(&self) -> bool { + match self { + &DisputeStatus::ConcludedAgainst(_) => true, + _ => false, + } + } + /// Transition the status to a new status after observing the dispute has concluded for the candidate. /// This may be a no-op if the status was already concluded. - pub fn concluded_for(self, now: Timestamp) -> DisputeStatus { + pub fn conclude_for(self, now: Timestamp) -> DisputeStatus { match self { DisputeStatus::Active | DisputeStatus::Confirmed => DisputeStatus::ConcludedFor(now), DisputeStatus::ConcludedFor(at) => DisputeStatus::ConcludedFor(std::cmp::min(at, now)), @@ -81,7 +100,7 @@ impl DisputeStatus { /// Transition the status to a new status after observing the dispute has concluded against the candidate. /// This may be a no-op if the status was already concluded. - pub fn concluded_against(self, now: Timestamp) -> DisputeStatus { + pub fn conclude_against(self, now: Timestamp) -> DisputeStatus { match self { DisputeStatus::Active | DisputeStatus::Confirmed => DisputeStatus::ConcludedAgainst(now), diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs index 4551ce9855e3..da0a0eca80be 100644 --- a/node/primitives/src/lib.rs +++ b/node/primitives/src/lib.rs @@ -30,10 +30,10 @@ use parity_scale_codec::{Decode, Encode, Error as CodecError, Input}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use polkadot_primitives::v2::{ - BlakeTwo256, CandidateCommitments, CandidateHash, CollatorPair, CommittedCandidateReceipt, - CompactStatement, EncodeAs, Hash, HashT, HeadData, Id as ParaId, OutboundHrmpMessage, - PersistedValidationData, SessionIndex, Signed, UncheckedSigned, UpwardMessage, ValidationCode, - ValidatorIndex, MAX_CODE_SIZE, MAX_POV_SIZE, + BlakeTwo256, BlockNumber, CandidateCommitments, CandidateHash, CollatorPair, + CommittedCandidateReceipt, CompactStatement, EncodeAs, Hash, HashT, HeadData, Id as ParaId, + OutboundHrmpMessage, PersistedValidationData, SessionIndex, Signed, UncheckedSigned, + UpwardMessage, ValidationCode, ValidatorIndex, MAX_CODE_SIZE, MAX_POV_SIZE, }; pub use sp_consensus_babe::{ AllowedSlots as BabeAllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch, @@ -71,10 +71,30 @@ pub const BACKING_EXECUTION_TIMEOUT: Duration = Duration::from_secs(2); /// /// This is deliberately much longer than the backing execution timeout to /// ensure that in the absence of extremely large disparities between hardware, -/// blocks that pass backing are considerd executable by approval checkers or +/// blocks that pass backing are considered executable by approval checkers or /// dispute participants. +/// +/// NOTE: If this value is increased significantly, also check the dispute coordinator to consider +/// candidates longer into finalization: `DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION`. pub const APPROVAL_EXECUTION_TIMEOUT: Duration = Duration::from_secs(12); +/// How many blocks after finalization an information about backed/included candidate should be +/// kept. +/// +/// We don't want to remove scraped candidates on finalization because we want to +/// be sure that disputes will conclude on abandoned forks. +/// Removing the candidate on finalization creates a possibility for an attacker to +/// avoid slashing. If a bad fork is abandoned too quickly because another +/// better one gets finalized the entries for the bad fork will be pruned and we +/// might never participate in a dispute for it. +/// +/// This value should consider the timeout we allow for participation in approval-voting. In +/// particular, the following condition should hold: +/// +/// slot time * `DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION` > `APPROVAL_EXECUTION_TIMEOUT` +/// + slot time +pub const DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION: BlockNumber = 10; + /// Linked to `MAX_FINALITY_LAG` in relay chain selection, /// `MAX_HEADS_LOOK_BACK` in `approval-voting` and /// `MAX_BATCH_SCRAPE_ANCESTORS` in `dispute-coordinator` @@ -90,9 +110,7 @@ pub const MAX_FINALITY_LAG: u32 = 500; pub struct SessionWindowSize(SessionIndex); #[macro_export] -/// Create a new checked `SessionWindowSize` -/// -/// which cannot be 0. +/// Create a new checked `SessionWindowSize` which cannot be 0. macro_rules! new_session_window_size { (0) => { compile_error!("Must be non zero"); @@ -385,7 +403,7 @@ impl std::fmt::Debug for CollationGenerationConfig { pub struct AvailableData { /// The Proof-of-Validation of the candidate. pub pov: std::sync::Arc, - /// The persisted validation data needed for secondary checks. + /// The persisted validation data needed for approval checks. pub validation_data: PersistedValidationData, } diff --git a/node/service/Cargo.toml b/node/service/Cargo.toml index 90036b57484e..376010fbc6d7 100644 --- a/node/service/Cargo.toml +++ b/node/service/Cargo.toml @@ -1,66 +1,68 @@ [package] name = "polkadot-service" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" rust-version = "1.60" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] # Substrate Client -sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -babe = { package = "sc-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-client-db = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-sync-state-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -service = { package = "sc-service", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -telemetry = { package = "sc-telemetry", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +babe = { package = "sc-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", package = "sp-beefy" , branch = "polkadot-v0.9.36" } +beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +mmr-gadget = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-client-db = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-sync-state-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +service = { package = "sc-service", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +telemetry = { package = "sc-telemetry", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } # Substrate Primitives -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -grandpa_primitives = { package = "sp-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-offchain = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +grandpa_primitives = { package = "sp-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-offchain = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-storage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } # Substrate Pallets -pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-im-online = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-im-online = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } # Substrate Other -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -prometheus-endpoint = { package = "substrate-prometheus-endpoint", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +prometheus-endpoint = { package = "substrate-prometheus-endpoint", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } # External Crates futures = "0.3.21" @@ -69,9 +71,10 @@ gum = { package = "tracing-gum", path = "../gum/" } serde = { version = "1.0.137", features = ["derive"] } serde_json = "1.0.81" thiserror = "1.0.31" -kvdb = "0.12.0" -kvdb-rocksdb = { version = "0.16.0", optional = true } -parity-db = { version = "0.3.16", optional = true } +kvdb = "0.13.0" +kvdb-rocksdb = { version = "0.17.0", optional = true } +parity-db = { version = "0.4.2", optional = true } + async-trait = "0.1.57" lru = "0.8" diff --git a/node/service/chain-specs/kusama.json b/node/service/chain-specs/kusama.json index ec1b8aa0503a..581f40aff4d6 100644 --- a/node/service/chain-specs/kusama.json +++ b/node/service/chain-specs/kusama.json @@ -19,7 +19,13 @@ "/dns/kusama-bootnode-0.paritytech.net/tcp/30333/p2p/12D3KooWSueCPH3puP2PcvqPJdNaDNF3jMZjtJtDiSy35pWrbt5h", "/dns/kusama-bootnode-0.paritytech.net/tcp/30334/ws/p2p/12D3KooWSueCPH3puP2PcvqPJdNaDNF3jMZjtJtDiSy35pWrbt5h", "/dns/kusama-bootnode-1.paritytech.net/tcp/30333/p2p/12D3KooWQKqane1SqWJNWMQkbia9qiMWXkcHtAdfW5eVF8hbwEDw", - "/dns/kusama-bootnode.dwellir.com/tcp/30333/ws/p2p/12D3KooWFj2ndawdYyk2spc42Y2arYwb2TUoHLHFAsKuHRzWXwoJ" + "/dns/kusama-bootnode.dwellir.com/tcp/30333/ws/p2p/12D3KooWFj2ndawdYyk2spc42Y2arYwb2TUoHLHFAsKuHRzWXwoJ", + "/dns/boot.stake.plus/tcp/31333/p2p/12D3KooWLa1UyG5xLPds2GbiRBCTJjpsVwRWHWN7Dff14yiNJRpR", + "/dns/boot.stake.plus/tcp/31334/wss/p2p/12D3KooWLa1UyG5xLPds2GbiRBCTJjpsVwRWHWN7Dff14yiNJRpR", + "/dns/boot-node.helikon.io/tcp/7060/p2p/12D3KooWL4KPqfAsPE2aY1g5Zo1CxsDwcdJ7mmAghK7cg6M2fdbD", + "/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" ], "telemetryEndpoints": [ [ diff --git a/node/service/chain-specs/polkadot.json b/node/service/chain-specs/polkadot.json index af4d42301c70..8fc8ac63ba32 100644 --- a/node/service/chain-specs/polkadot.json +++ b/node/service/chain-specs/polkadot.json @@ -19,7 +19,13 @@ "/dns/p2p.5.polkadot.network/tcp/30333/p2p/12D3KooWSRjL9LcEQd5u2fQTbyLxTEHq1tUFgQ6amXSp8Eu7TfKP", "/dns/cc1-0.parity.tech/tcp/30333/p2p/12D3KooWSz8r2WyCdsfWHgPyvD8GKQdJ1UAiRmrcrs8sQB3fe2KU", "/dns/cc1-1.parity.tech/tcp/30333/p2p/12D3KooWFN2mhgpkJsDBuNuE5427AcDrsib8EoqGMZmkxWwx3Md4", - "/dns/polkadot-bootnode.dwellir.com/tcp/30333/ws/p2p/12D3KooWKvdDyRKqUfSAaUCbYiLwKY8uK3wDWpCuy2FiDLbkPTDJ" + "/dns/polkadot-bootnode.dwellir.com/tcp/30333/ws/p2p/12D3KooWKvdDyRKqUfSAaUCbYiLwKY8uK3wDWpCuy2FiDLbkPTDJ", + "/dns/boot.stake.plus/tcp/30333/p2p/12D3KooWKT4ZHNxXH4icMjdrv7EwWBkfbz5duxE5sdJKKeWFYi5n", + "/dns/boot.stake.plus/tcp/30334/wss/p2p/12D3KooWKT4ZHNxXH4icMjdrv7EwWBkfbz5duxE5sdJKKeWFYi5n", + "/dns/boot-node.helikon.io/tcp/7070/p2p/12D3KooWS9ZcvRxyzrSf6p63QfTCWs12nLoNKhGux865crgxVA4H", + "/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" ], "telemetryEndpoints": [ [ diff --git a/node/service/chain-specs/westend.json b/node/service/chain-specs/westend.json index c183622d66c9..6527d81001df 100644 --- a/node/service/chain-specs/westend.json +++ b/node/service/chain-specs/westend.json @@ -11,7 +11,13 @@ "/dns/3.westend.paritytech.net/tcp/30333/p2p/12D3KooWGi1tCpKXLMYED9y28QXLnwgD4neYb1Arqq4QpeV1Sv3K", "/dns/3.westend.paritytech.net/tcp/30334/ws/p2p/12D3KooWGi1tCpKXLMYED9y28QXLnwgD4neYb1Arqq4QpeV1Sv3K", "/dns/westend-connect-0.polkadot.io/tcp/443/wss/p2p/12D3KooWNg8iUqhux7X7voNU9Nty5pzehrFJwkQwg1CJnqN3CTzE", - "/dns/westend-connect-1.polkadot.io/tcp/443/wss/p2p/12D3KooWAq2A7UNFS6725XFatD5QW7iYBezTLdAUx1SmRkxN79Ne" + "/dns/westend-connect-1.polkadot.io/tcp/443/wss/p2p/12D3KooWAq2A7UNFS6725XFatD5QW7iYBezTLdAUx1SmRkxN79Ne", + "/dns/boot.stake.plus/tcp/32333/p2p/12D3KooWK8fjVoSvMq5copQYMsdYreSGPGgcMbGMgbMDPfpf3sm7", + "/dns/boot.stake.plus/tcp/32334/wss/p2p/12D3KooWK8fjVoSvMq5copQYMsdYreSGPGgcMbGMgbMDPfpf3sm7", + "/dns/boot-node.helikon.io/tcp/7080/p2p/12D3KooWRFDPyT8vA8mLzh6dJoyujn4QNjeqi6Ch79eSMz9beKXC", + "/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" ], "telemetryEndpoints": [ [ @@ -131,4 +137,4 @@ "childrenDefault": {} } } -} +} \ No newline at end of file diff --git a/node/service/res/rococo.json b/node/service/res/rococo.json deleted file mode 100644 index ba1ad29cdd82..000000000000 --- a/node/service/res/rococo.json +++ /dev/null @@ -1,211 +0,0 @@ -{ - "name": "Rococo", - "id": "rococo_v2_2", - "chainType": "Live", - "bootNodes": [ - "/ip4/34.90.151.124/tcp/30333/p2p/12D3KooWF7BUbG5ErMZ47ZdarRwtpZamgcZqxwpnFzkhjc1spHnP", - "/ip4/34.90.137.14/tcp/30333/p2p/12D3KooWLcpkpvjr5ccgtUdTSYtNDjEdsDcPNrt2Rb7yXuAf7bUE", - "/ip4/35.204.67.254/tcp/30333/p2p/12D3KooWGjEEDmNbBkXLM1uKMseK9iYD3osKA4JGdGKMZDCusjd6", - "/ip4/34.90.121.39/tcp/30333/p2p/12D3KooWBhkZQydNHDR3XSehnrfj1KNFCdpwgDrYpX54FrUR1FRS", - "/ip4/34.91.145.35/tcp/30333/p2p/12D3KooWBuLAMevZexnFKCgTyoz3AnHQn98D9cfe1Mg3kPoCjkwf", - "/ip4/34.91.77.80/tcp/30333/p2p/12D3KooWA5BAM71y9NtV5NH6EjANgYKRZ8jNLJ5z8GJ5RPdjt63n", - "/ip4/34.91.84.25/tcp/30333/p2p/12D3KooWSV4VqhBHZKKBsZKmVU462qRW9PmXTSuYvuajt1P93djA", - "/ip4/34.91.97.19/tcp/30333/p2p/12D3KooWD6wC88atMMyVeP6ZKg9sK7QmUL8x8m1RxMW8rhv2vWyg" - ], - "telemetryEndpoints": [ - [ - "/dns/telemetry.polkadot.io/tcp/443/x-parity-wss/%2Fsubmit%2F", - 0 - ] - ], - "protocolId": "rococo", - "properties": { - "ss58Format": 42, - "tokenDecimals": 12, - "tokenSymbol": "ROC" - }, - "forkBlocks": null, - "badBlocks": null, - "lightSyncState": null, - "codeSubstitutes": {}, - "genesis": { - "raw": { - "top": { - "0x06de3d8a54d27e44a9d5ce189618f22d4e7b9012096b41c4eb3aaf947f6ea429": "0x0200", - "0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385": "0x0000300000800000080000000000100000c8000005000000050000000200000002000000000050000000100000e8764817000000040000000400000000000000000000000000000000000000000000000000000000000000000000000800000000200000040000000400000000001000b00400000000000000000000140000000400000004000000000000000000060000006400000002000000c8000000020000001900000000000000020000000200000000c817a804000000000200000005000000", - "0x084e7f70a295a190e2e33fd3f8cdfcc24e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x08c41974a97dbf15cfbec28365bea2da4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x08c41974a97dbf15cfbec28365bea2da5e0621c4869aa60c02be9adcc98a0d1d": "0x20034f68c5661a41930c82f26a662276bf89f33467e1c850f2fb8ef687fe43d6227603a90c2bb6d3b7000020f6152fe2e5002fa970fd1f42aafb6c8edda8dacc2ea77e039d065fe4f9234f0a4f13cc3ae585f2691e9c25afa469618abb6645111f607a530307d29bbf6a5c4061c2157b44fda33b7bb4ec52a5a0305668c74688cedf288d5802fb0330356e63a35dd930bc74525edf28b3bf5eb44aab9e9e4962c8309aaba6a6020019a8bb188f8145d02fa855e9c36e9914457d37c500e03634b5223aa5702474033f1a6d47fe86f88934e4b83b9fae903b92b5dcf4fec97d5e3e8bf4f39df03685025e84e95ed043e387ddb8668176b42f8e2773ddd84f7f58a6d9bf436a4b527986", - "0x08c41974a97dbf15cfbec28365bea2da8f05bccc2f70ec66a32999c5761156be": "0x0000000000000000", - "0x08c41974a97dbf15cfbec28365bea2daaacf00b9b41fda7a9268821c2a2b3e4c": "0x20034f68c5661a41930c82f26a662276bf89f33467e1c850f2fb8ef687fe43d6227603a90c2bb6d3b7000020f6152fe2e5002fa970fd1f42aafb6c8edda8dacc2ea77e039d065fe4f9234f0a4f13cc3ae585f2691e9c25afa469618abb6645111f607a530307d29bbf6a5c4061c2157b44fda33b7bb4ec52a5a0305668c74688cedf288d5802fb0330356e63a35dd930bc74525edf28b3bf5eb44aab9e9e4962c8309aaba6a6020019a8bb188f8145d02fa855e9c36e9914457d37c500e03634b5223aa5702474033f1a6d47fe86f88934e4b83b9fae903b92b5dcf4fec97d5e3e8bf4f39df03685025e84e95ed043e387ddb8668176b42f8e2773ddd84f7f58a6d9bf436a4b527986", - "0x1405f2411d0af5a7ff397e7c9dc68d194e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x1405f2411d0af5a7ff397e7c9dc68d196323ae84c43568be0d1394d5d0d522c4": "0x02000000", - "0x1809d78346727a0ef58c0fa03bafa3234e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x196e027349017067f9eb56e2c4d9ded54e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x1a736d37504c2e3fb73dad160c55b2914e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x1cb6f36e027abb2091cfb5110ab5087f4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x1cb6f36e027abb2091cfb5110ab5087f5e0621c4869aa60c02be9adcc98a0d1d": "0x20a076ef1280d768051f21d060623da3ab5b56944d681d303ed2d4bf658c5bed35010000000000000038757d0de00a0c739e7d7984ef4bc01161bd61e198b7c01b618425c16bb5bd5f0100000000000000d2644c1ab2c63a3ad8d40ad70d4b260969e3abfe6d7e6665f50dc9f6365c9d2a0100000000000000764186bc30fd5a02477f19948dc723d6d57ab174debd4f80ed6038ec960bfe2101000000000000007c94715e5dd8ab54221b1b6b2bfa5666f593f28a92a18e28052531de1bd808130100000000000000bab3cccdcc34401e9b3971b96a662686cf755aa869a5c4b762199ce531b12c5b0100000000000000720537e2c1c554654d73b3889c3ef4c3c2f95a65dd3f7c185ebe4afebed783720100000000000000da6b2df18f0f9001a6dcf1d301b92534fe9b1f3ccfa10c49449fee93adaa83490100000000000000", - "0x1cb6f36e027abb2091cfb5110ab5087f66e8f035c8adbe7f1547b43c51e6f8a4": "0x00000000", - "0x1cb6f36e027abb2091cfb5110ab5087faacf00b9b41fda7a9268821c2a2b3e4c": "0x20a076ef1280d768051f21d060623da3ab5b56944d681d303ed2d4bf658c5bed35010000000000000038757d0de00a0c739e7d7984ef4bc01161bd61e198b7c01b618425c16bb5bd5f0100000000000000d2644c1ab2c63a3ad8d40ad70d4b260969e3abfe6d7e6665f50dc9f6365c9d2a0100000000000000764186bc30fd5a02477f19948dc723d6d57ab174debd4f80ed6038ec960bfe2101000000000000007c94715e5dd8ab54221b1b6b2bfa5666f593f28a92a18e28052531de1bd808130100000000000000bab3cccdcc34401e9b3971b96a662686cf755aa869a5c4b762199ce531b12c5b0100000000000000720537e2c1c554654d73b3889c3ef4c3c2f95a65dd3f7c185ebe4afebed783720100000000000000da6b2df18f0f9001a6dcf1d301b92534fe9b1f3ccfa10c49449fee93adaa83490100000000000000", - "0x1cb6f36e027abb2091cfb5110ab5087fdc6b171b77304263c292cc3ea5ed31ef": "0x0100000000000000040000000000000002", - "0x2099d7f109d6e535fb000bba623fd4404c014e6bf8b8c2c011e7290b85696bb3": "0x20f49eae66a0ac9f610316906ec8f1a0928e20d7059d76a5ca53cbcb5a9b50dd3cf6f8fe475130d21165446a02fb1dbce3a7bf36412e5d98f4f0473aed9252f3492c57f81fd311c1ab53813c6817fe67f8947f8d39258252663b3384ab4195494d2496f28d887d84705c6dae98aee8bf90fc5ad10bb5545eca1de6b68425b70f7c306ac5c772fe858942f92b6e28bd82fb7dd8cdd25f9a4626c1b0eee075fcb531160ea09c5717270e958a3da42673fa011613a9539b2e4ebcad8626bc117ca04a64d59feddb3d00316a55906953fb3db8985797472bd2e6c7ea1ab730cc339d7f4e262811acdfe94528bfc3c65036080426a0e1301b9ada8d687a70ffcae99c26", - "0x2099d7f109d6e535fb000bba623fd4404e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x2099d7f109d6e535fb000bba623fd4409f99a2ce711f3a31b2fc05604c93f179": "0x20f49eae66a0ac9f610316906ec8f1a0928e20d7059d76a5ca53cbcb5a9b50dd3cf6f8fe475130d21165446a02fb1dbce3a7bf36412e5d98f4f0473aed9252f3492c57f81fd311c1ab53813c6817fe67f8947f8d39258252663b3384ab4195494d2496f28d887d84705c6dae98aee8bf90fc5ad10bb5545eca1de6b68425b70f7c306ac5c772fe858942f92b6e28bd82fb7dd8cdd25f9a4626c1b0eee075fcb531160ea09c5717270e958a3da42673fa011613a9539b2e4ebcad8626bc117ca04a64d59feddb3d00316a55906953fb3db8985797472bd2e6c7ea1ab730cc339d7f4e262811acdfe94528bfc3c65036080426a0e1301b9ada8d687a70ffcae99c26", - "0x26aa394eea5630e07c48ae0c9558cef74e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x26aa394eea5630e07c48ae0c9558cef75684a022a34dd8bfa2baaf44f172b710": "0x01", - "0x26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc": "0x4545454545454545454545454545454545454545454545454545454545454545", - "0x26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c118746b4def25cfda6ef3a00000000": "0x4545454545454545454545454545454545454545454545454545454545454545", - "0x26aa394eea5630e07c48ae0c9558cef7a7fd6c28836b9a28522dc924110cf439": "0x01", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9050f9ffb4503e7865bae8a399c89a5da52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da90d10cc4959af6a68eba3bc06d5c7bc28520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a": "0x0000000001000000010000000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da914076ec446ba6876ba5cb99bdb7129be8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47": "0x0000000001000000010000000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da945315c068df2baa1c677b9b3e81f7439fa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00": "0x0000000001000000010000000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9935ae9d4cb148940af99a366d100d5af02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864": "0x0000000001000000010000000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da995445d4efb6eae1971fb125f6190c49202a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16": "0x0000000001000000010000000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da99677d775b618280f5c76d192b43ea38c38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404": "0x0000000001000000010000000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9a606acaa4558183a2102457959a213a192ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f": "0x0000000001000000010000000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9b483908290ae9b936c519917440306ea62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a": "0x0000000001000000010000000000000000407a10f35a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "0x26aa394eea5630e07c48ae0c9558cef7f9cce9c888469bb1a0dceaa129672ef8": "0x998f18726f636f636f", - "0x2762c81376aaa894b6f64c67e58cc6504e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x2b06af9719ac64d755623cda8ddd9b944e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x2b06af9719ac64d755623cda8ddd9b949f99a2ce711f3a31b2fc05604c93f179": "0x2086975a37211f8704e947a365b720f7a3e2757988eaa7d0f197e83dba355ef74348a910c0af90898f11bd57d37ceaea53c78994f8e1833a7ade483c9a84bde055ee93e26259decb89afcf17ef2aa0fa2db2e1042fb8f56ecfb24d19eae86298788e95b9b5b4dc69790b67b566567ca8bf8cdef3a3a8bb65393c0d1d1c87cd2d2cd2f9d537ffa59919a4028afdb627c14c14c97a1547e13e8e82203d2049b15b1ac4a980da30939d5bb9e4a734d12bf81259ae286aa21fa4b65405347fa40eff35560d90ca51e9c9481b8a9810060e04d0708d246714960439f804e5c6f40ca65192156f54a114ee191415898f2da013d9db6a5362d6b36330d5fc23e27360ab66", - "0x2b46c0ae62c8114b3eda55630f11ff3a0f4cf0917788d791142ff6c1f216e7b3": "0x00", - "0x2b46c0ae62c8114b3eda55630f11ff3a4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x2b46c0ae62c8114b3eda55630f11ff3afe6d4a58cccf03d052c50ccbfa0311c7": "0x52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649", - "0x2ce461329fdf4be12bce01afc0af09bc4e7b9012096b41c4eb3aaf947f6ea429": "0x0400", - "0x2ce461329fdf4be12bce01afc0af09bcba7fb8745735dc3be2a2c61a72c39e78": "0x00", - "0x2f85f1e1378cb2d7b83adbaf0b5869c24e7b9012096b41c4eb3aaf947f6ea429": "0x0100", - "0x2f85f1e1378cb2d7b83adbaf0b5869c2ff3ae12770bea2e48d9bde7385e7a25f": "0x0000000002000000", - "0x31a3a2ce3603138b8b352e8f192ca55a4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x38653611363acac183fe5c86aa85f77b0f4cf0917788d791142ff6c1f216e7b3": "0x00", - "0x38653611363acac183fe5c86aa85f77b4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x38653611363acac183fe5c86aa85f77bfe6d4a58cccf03d052c50ccbfa0311c7": "0x52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649", - "0x3a636f6465": "0x52bc537646db8e0528b52ffd00589c9b044ee2c5de12521040ec381d7b04e003d545abfe38ed9fa1139deccebf67615500b32060027cf47266f80b144514ee1f24fb3e00147918a63b7e9769dcb9893ce34affc1f8d444582ee9d0da8bf9b4a4edddd6a4dc52ca245300146f118812debec5fa7981f98060a217cde557243f89972407b50bf301c1d09bb364bef4395dfa8cb0189b328e31d385ecd90c175f3c09cf66b8b0c1475934dad8b3ce5d9222994473a08e689e5acd4fcebe719742f5e9f2db9a9bab32de9c9f75f9f1d72f2c927f72eb5be4e6f413ab5da7d9ae7679edf5e6c7ea1675edeb1878d337e6e44743bb66f5f0f527e776593fdd50bae69be466978276713cf96345f250bf21b3093d2b65bce921b379eab14ba1a85bd4a7db6f768b528f322039bff8f2e35ec84d198fd17c943d752bedd29c7a51ff783299cc08a43edb255dd39cfd815a7e5cb73cf933414a7dce6bbb45576678a17deadeaef8d459a840bbd80c173478ea50da359d7a0cf184f8d4b92559fe443034e21fbacb64321965359e8221b7f111cdf307311a29135bf4703e530fb967e7fe690f8b3c7b88e499c93c3bf3117ef656bba4b397d03f1664d7be8d1be0b1193cb8fcead9cc1d5fbe7f782693c9b680a1ce6bcefdc360b8f39ab3fc29a263698c991cee88a2095073db2efa9a6b666240e6b51b4ef1f9e8f32ef1f8a3b3fcb1608c2ebffe66f3445f80c77a9e19cd5e7b3633861c1f9d77222cc6a26c208c968cbab0095e7b685f4a97d2a57429d7bc9452ca2958c86099e28a173d3eb709ecdc6d6c82c7331cd8bcb7abbd27ab5ded3bed9adf331cbef876ae7f24383f2cf2adf3edd1a7ca163d7efea465774be9f6e5cd59229dba6c79c3f83dbf7d8b2ea38732ba748e2e4572fc269bbf72a3ea9ffd15addb24c77c247a18c697cebec90ff4a4b3739782bc76935cfce47757344ecd5fe1527c6428ca5e08858fdededd0a5326fbe8b153c1937d74ae5dfc2de38f77bae1d8f8b95d613bfb6c8f1eb273b7b85bd34ff0da576897c2f20275ace3033636c19b1eb29eba4fbb426ba45da1d76a57e8f3d4a997d02ef974a6658fa7aed33f0d2279fa6191a7eeb5ab9d3a4ebba453a7ceb52b3a75dea1570acf9e3f88c508dbd87927f479e91b7ff1b7d82599dd8acedd8a372c923f3b7649e255613a7ffcdbc65d0ada0dfd35b7dd715ccd6eddb0483eca59edda5cba4ebbea564fa71b9e1ce5a7ca79cfeeb5abba749c769d5cfa56bff8dbe9e36e71b7388f5d0af167b7b81b728ef2faf1735f91fc936fb139ca14d78f7ffbf85127d6b35bf993c5416e1ee69e50e7f9869a5397be49e6f985f1855060b75f117de6be7ddb9ae34ebbf1e32fb4cf2e3b8e2beed6363be615d7ad9d6e49afeeddaa52fbe60de36bce9ff771b7dae9b5dd6a8fd52e7ee9f3e3f776b14bb7f267caa4b7f8880c775ebacff3073154a4406c8c82c7331c64cf33591b023ccf6ec8e2fddbb93b803793a9f9707e3b50dbe8d6b2fce1e609bd8f1e7a1fda6f9fed626fe77669ce3edb55fdd9b7faf16b5ffc8d5d9ee4629744bbd1abce9d02b8fa163b1534af37d45cf3ad3b15bcd79cbbd9ade9dc25a10ed49a732737eeec0d636fbd7ea1d5ea17ceafce5d12eb5bfdc2047cf58dbbd30d69f893d72fe4d957d7be5053000b15681283959086afceddaa0e24b58ffff409c9a6a6a636af79fd42243f7d8b5cfda6af50bfda4fa8be76c3f8f50ac5a6a6a6a60f634f7d8b9cf6f17357249f5eee56383fce8fbb155d7edcad10e7a38d92065b689f7deb2f7efc62e4fae39feda2cebec5c8d1e85b73ecb50bb929e3496fa72ebb24f4462ffa2639fac5ef2e3a77d2819abb24ed40bd452e7efcfdc5e7ce01fcd1811aa86331c620362ec1db54bc137a2f9ddb159d9ddbd53e3d7eb35bd237767931b42f9dbb24dc2de9408dc48b1f3d273a7fdf9c25df3767493bf5767a8be2c7cbdd9a379ccf2e9d3b15a2f70ddba30335efc82bc57bfe202663d4b231f3784653e9036fc46c6432990c04c366ca183d3fef6cec5300233f1ed38d39e085f6db6dbbf8cc962fdfceb58b673aecf1ed5ebbd8db71da15bd9dc547e2b7f34e5f29fefc412cc6036c6c82c7b31b9af8d03ebb6d179b0981d2b373fd13417656bbf8cc962fcfceede20f759e9d77f84af1e70f6231a2b045e77685ecf172b7d8d9633102d97826537aae1b1ff1986e3c82c774638f9db51b2662087850037513829b2e6e966e98b8a9e2868a9b296ebedc3c71e3e546e9e6881b236e8ab821e266cb8d969b1d6e926eb2dce87063c58d183739dcdc7003c52a8f559b550d563458cdb18a63b56645c7ca8e951c2b19ac62b072c1aa05ab345667b83cb8369c1e1c08382e1c0f1c10dc0f9c0fa81b5032ef0ecf0e0f0d6f049b0bb637b6156c6a6e94d854b0b5b1bd80bb6263c1c6060148e0acf0f8f0fa885be20e148b150bb61678676c29e0be705eba341c145c976e0d6e89ee049d09ec169c0cb8187071706b6e3e10e3886b221c2b34d104f18cf845f42286207211bb8860c4302b36918aa844548a4944282212f188d8438ca2862a110c021e88861b2c6ea4b8e97223c44d10ab3e567cace0882058c160a566c586b78757038f8de6a17ff0d27866bc32decc138117860786f7851782d50a566e785a78597408bc2b3c2bbc25af0acf8bf784e784d784f78317c40d12de0e1e17ef03de164f8be7c3cd105e0f1e083c1dbc2c1e9277e4dde0f1e02579407846374edc347103e626899b28547aa8f250e1a1ba4355c70a05ab363cd9cd152a3b54365035a9fa50f1e1e5e0e1e009e161f186f0ba784578447848b416ef8866c333228aa7e429e12da1da437503ef8b97840785278537455be151e181692e3c2cbc2d9a098f0baf0b2f8ce785c784aa062a1a44362b3d3c31de18151b151daa39542f50bda17281aa052a16a8e450c9401503551caa14a8d2f41d2a13a8d450ad81a22a818a04aa349ca8d0509da13aa32aa31a41935199a12a4345a6cbb4193d46f5850a8e88874a0b150c5457a8c0a8a2504111cfa89a5031a15a428584ea8898864a8d6a052a37542a50b5a162438502d51aaa13a8d0a8cca8985464a8c65089a11aa312a39af50854225085d16ba8c05079a10a81aa0b551815172d856a0b55162a2c5456a8965455a8a8504da19242f545e545f584ca099512ab3556275029a99258eda132623503551755102a20543fa87c50f5a002818a8b8a07d50eaa2d2a2daa0fa87450655125a9725021a98e5446b10f1516150eaa1b54b25453aa8f141fa93d523748e991ca23d5268547ea8e941da93a523648d5204583149b141da939523348c99192412a06a938526b5270a460907a41ea8d940b522d48b120a526b582941b2915a4da48a520c5460a059d269526b546ea0429133409526aa44a9022412a8d149ad4085268a4ce489d49994995499991628a364895912223ee911a23e6912293122335262526354b892015460a8cd417292f52214875910a93e2a275486d91d22295450a8bd415292b524ba92a5254a4c0a4a64849b181541441a92f195821e525f544ca89541329266209524ba4944829a590481d91322255447b91222235449f91ead245b4999410a9205240a47ee834fa8ac622e543aa8714081a4d8a87d40ea92d292da90fb41a291d52595249a91c5248a9a394510a4b0a87d40d2959d7d4f5d1f1d135e8f6e86ed0e9d1b5e9f0e8eee8ece8eae86c10f9e8681069d0b1e9e8e8e6e866d0c9d1c9a08b411747b7a683a38341f782ee8d488278829882a882e846c7824e4db7824e055d1b5d0a3a2a3a293a2864e888e8ba6c6e7419dc1b340ad40fa71870479c487042e374e654866e59313920d6204e11da312c192b869dc52f560aeb846de274c349566b506950d9d434aa1755899ad464687468736040fba2c94e655010502e9407bac38c63aee9281a8afe32e1e8144c30e617d38b1982d9c50c33b9985b4c2d6616138b79c5b4622ecd2a261513cc9c624a31a39850cc2fd3cb7c623a319b984ccc25a612536926319198474c236611938839c4ec328598414c20e60fd387d9c304c11c437e21ef9075c81a4c2e720a29850442fe20b934974e872e8bb4414463950215a21d5d47b3a0db50cda051d054f4091a4c97a04dd04274108d469fe92e2d467b693bba8916d3b3164187d15f7416fd443bd15d749806416fd15af45257d14b7851f4144d4403d13da8daf496fe40dfb0c26355c7ca06ab3b5a169be20da21e2b15c4360d46bc23d611a5886ae20a220a621b918d9826ae11d588238868a219f1892882e825865114bb442162d2ea054f5c68c2a46d008107b0b04ac38024318788348386658bcf719be3d43288c8890b4cac38098a8109932d4a285482983041710c9ae28293222a33bcc0a4e849d050142854a23061d201b82a23e885105663709517a8446152c350d00c424ca258f9222a4132d4e084055f91e1a02754aa5061e2e409952a0e28a2324395274f7ec84a0c0a546921849518269a12c54951082b117050d00b5688a240a96128e84a942941509804c1e084882848062641454e648852441444c509038a6658a14a0be02a0c0af80a0c86524414e44291922a4faa3ca902015f7dc14444415386acbaf8b1e242860600596dc14541444c5e080a0283acb48052e549101422ab2b98a88620294435042d89c0b7b2228a95af81284a026af86fb564c2aa8a9d15154c4310959bd5142c05c7f0a48a95a09c55143c34030c515ea052e5099328563ec8052720901514fc42952a43569858891203d15010150e54615243909410565f184a101518a2105199e149952b5166100a62523454c54ad090919517861285495110d1d00c4f3a583dc14441518aa20c5589a16806274c606012c5ca3bb102858a93a1143c5839c131103989e1ae9ae0a0212b4c8286a2cc201434c484e8852b563e5831c14554826478e18a95d66a09260a2aaa728509132a5574564a700d2e3051229a1244858a93189e30b122c3500c4ca05099a18a0b54a2245144a5ca13264232404182abbc2064750413155109ba126404c340250a142a4156980415398112050a15274f8aac88e02028559e0c590dc143555e200a22eac244453358299aa10a005642c83003119113105641b0932227509850a912054a50115114a2a1202b21ac7e60a2a0a12a4f98d45014654a14179c4c89e2e48a135ff9c0445666a8320403130f563d30d1509522a22a0a7032e48405d60a04cc8128567e2848ca50150aacf0ad78e0a0a019826678400b50826080c1490b0258edc044529e04c5f0e4034c544425682828062a517ca50395282fe4ac92f84914222a51868a68086252c3142b569c30190a823225ca0ca0942755a6803aab1c5806264e8a9c40715214d480d50aa90351a638895214854a14202b2c2ce54995292e30092a9ae149100d4137ab1b78a80a02b802a86650cf84217b8e6d3c93c93ec664079a66a419452bb14e0738801da044093b8063571b7b7a8c6de79c3172c719a38c316a3a761a891d7f749fdaf68fd38ffef1e3c70ffba3fef8f1a3fbc7cd8f031c20c638edecd81e489dda5a03ba67b436ced90ce8396b5beeee1b5bad6d59a34eb78e119d9eb556dbfdcd6e9f96534776cb960da43d38803cc9967d92f1a6bbb1dd9a66638cd6d6da565a1ba3ed8e4bdada8e76b64e4bdb3d75ba63b7d56ce5dab1da2a422f408bdd32ca18675b3b8fc4d8b635db5a6b5a5befeed6acd63dada6d99eadc54e75c78e9683b636c6d955848ed3da193bb6085fabd01da3eda980e63a6ddb38a38d1ed8e8d1ce4ea1bbdbcee9818dd146db6d7fda48f7eca9c91c2dce1bd6ec96dd9d806e4d2ae9197b769d75da6a6d12db1d13a0b5d6dd5384b693c5ddcd1c58db5adbd6348b80186337d8f3a6bbdaeeae3776d66a65d759a38db365db19bb3df8b6ed8165c58e76862025d06c96d69ad6f1a6234bb37dc362f54da3c0e2ee6aadd63707e88eb15b9bb36f0e60808ae484236dad2d809455d639abac56a7d66a44b694d2c88fab5a5bab35c184dad2846edb9a2dc1f6076d653701ac071a6bce683bf66c126ced683df0605a5b7b04db22d86eeba355dbd5dad64498db8c6d670fa035db13e4eb6e19bb88d6d14a29adb5d3fee8d93d7bdaee689bce9bad65cfc9415b3b5bb68c72f6b4d6f60f01f4a9bbb5ee68bb6dcfeeaedd76da1880386df368b69bd2793367dbd62a4e1b0200da76c7486476d7b6ddddb663b4316a52ca396dcf19a3edee39a5b4b5edec38bb6df79c33ce19a7bc892c0faa6ddbddd15adb5ac706618763e4183fb8d1c658ebac1cdbc6d8dd1d63d4b1dc9f9fe6241263dbe6c8b13d88733690d933760fd1b1ad9333e79cd1ce96b36dc78e1d59724b7b73737373d3379a7673336f98b87142762ecc40c4234394222a330c5dae8810274143424888f242d09095cb010c55a674000208ac29415782a630a1c1890c4c60a012050618aa4c21d2c150109520184e35044961f224ca141766b0d20a226222431528549c0c5d169428539c5c614214e583140d4131e8b062208a4225ca0bad189e14397121040e5a41608842f40129725244c444ca50150e140551d9c18142c50993a021275664a8f2a4043ac5c9932a535a1b0d4150a8446142258a93189ebcf042154fbd50340393222a5186ac30794214458621234009fae0079310444414346445862a4f980c055da9f2246888891322284f82988c20c5650209569e04fd449141862a4f5a529e387161ca942a4301b8e111a8548952f4c40911152743454c8a869c141185b00ac163125e885280114c308184212226558aacd430f4e40314511151141a8274ba1a82a43029a221888a071b8f00854a90152b4e744e42544c42952a434ca0040d054119aac2c46502094151868a0220c5c9932741527c23ea2095d375c01505c110c236e42468ca132641303819aa5244c404ca9428313c6152346506272f0441e129c135c46502094e43150e1479803242c2084c480892e2648a0b4c60a0122506222731b826830757a804c9c92330a152250ad150d015264141432f3019aa52e4e4499529539c3029a22148e70a952089c35dc35015198264d0ae5009923e2a2e9a292cb6d5580c0683c16032366130182c766ac230541386c16cd78461b00883c562131661b0d9040683c56c138ec534182c16ab4d3816a3b1da241661b209734c6bc2b0580c169331d90416b9492cc260b0d86c02636ec230182c269bc4620cd64d18d64d1806eb26b1088b4d6051ce26b1188b4d601116eb261c8b4d38168bc562b4097793588cc562b2c90a93059199a30c444e38409c01030924c4a4b9c2062083eca14f0b2e9381d1b5b42b84c8a56351ce25e4a41e63b594ba744bbd52aacd2f26e9e7326c9c911de5e2595ffc4d7271fa9d7276b7e0c90db6d883d7291edaf8265b8c3d78d143ae8bcff191e8ed5cbb38d6417df211cdd9e9a651eadcc9d0c61e3c8b72ba39b54ead53dfaca3ac757a724a29750ef88875f93cdbf22536b975e9cf62d644f13676d673aacbefcff90ac6ba76b2f5a3dddca1728b4d287e03d12505cea9f74714bf4f570afdc27eeaf11b8adc43bdc8be1037fde6dd29e11ce528df2e7520c97da78fa773cef9c9b78d6edca580f2537f61ecdbc3934be79c3b154ece395057df3c7e9b9f3ece65b7c47af478997ba20335f7857d23f7c4663f5db12f24fb903d7bfdc2a2f85aec1644d977943dfbd63f1df0a448e70fa32c0e343eae106f78be619475d3f9bb329f7d7e4b54cf2e3fe623e19c5748f51c72d387d2db81e4e742decb280b63e3feb13ebff8679e8af15a1bef5f95be789f9d0a2d3461e6c314fa283ae2c322190c6a3e2ce22213fab0a805683e7a380308ca38438d1a25283648bc103735f5b1c408163a3e268945785dc5f3ac4b976fa5e719106dbef53c03e2cbcb2e16e1c92d9e6746a4e0e3ec795644111f80e7191165bcf4d8ad6065328d9b9f7cfb19311aa2fa57fa61188a75deeab15b42bd6f385bc2889fde4e3b253326c64fa79f14ea2151ece7bd0244dbe827c44d4d4d2bf857af378cd1ef0a1025223f1da8fba362bcf615f54f8fdd12223f974c6fd73e29ad84aa40bddea2edb95b21cf9430e28bfa4a7c4d7efedae73f8bb6178a1f4378ee9208b5ece5773f764984a64cf6ed73d4e0ebf88d725aa784dbf8e81b534dd3b429a3a6d9562a7abffc7c1e1663b4b52abc107e56a9494d636f8ebacca95256b7da9753a3f6cd972fa3d44e272dc5cec7c74fbe5659c63a53cc6d3c7f7776ab9b7be2105edff0f47add0ae1e765752bd628d76c72935f24c22bf3461391082f3abfcf108d3c9ef950c70be0378e593cea928b0258a8400f6da494b2d5ae1ceac31b96ab40131fc84c704ef9831adfa940bbc2569376855e0ced9accf4d3a733c07ddac5b31fc2fcf412fa8782f366ae98def8c972fca43e3fbd48bb42e9ad1863a42ea933472fd29e3dfe4ebbe610538ff41322129dbb0544b951a94929bf50ba079efacb061b6015d6378c7dbb647bc37629f586d2d943295dded0866fe7ef8eee5b7f324aef25d1e592e89a4fd76917a51fbf87c3b31e46f0f4a3efe1b42bf2d1471fcf5d131761a75f6c7aee645c841da8e9d7b21b3e329b53161bc720521b47203cce4e211bc71fbc397d4eb75cbba48bd0ce9baaaf944fb2c74e092f61efe85373fef6f8b56fdad74e57d0bcbd7e52b44f73d93540f366153476ed8611f5859bc7ed93529dbd3b25f5e55567e7069c9c6fec846830c2e106d90fa19c28f628940b851cb8011f4d4fc468befca0c36f4e14fbed72b75037e425a7dba5807a4dd328a5734e296577c7f8b45312bfbab48efaf8e9c65c774a50979d764a50cfdc13a250394baab3b3d79006be52ac5bb75fa879bbf6f18a7b9e6d69e227f7d0cfb28c9d227d23c8c62678d1dbbdf666f9ed3c7ba73972f1da432e02205582ed79a603d319107ca1e5033af877002fb4d199394a87b2452cde5c6db35b382cb42bf42f588d9f3e5debe9af510f39cd6b6e447385d68ba15da11124ed92af7905da78cd33d03f13949c86c9bc86f3a11196bde63aedead7344d63d372b0583ad2bd76499c4f61932a15a853a7f2e3af9a7559ddba26a5662bfdaec497df95f8d63aad5eafbfbd52343fb96c8066bdba665dba2624ad157a51fa92c96437fc2639eeacd5340792dd25b1b56a5a6d2df62d5febe65e94524a29a542b5a9a9698fafbe35671da8e72724df5ea1ed869273f98545fd2947f9c65d12ee8af753a6ec860fad0bd53d6e68fa2bf6adcf4fcae69dbca11786a19d42d608871b7ee88af6d5afd4278a7d951fca6d281de5f216f5a7ae50dce3b7ee2beadf9cfb84e46f37478538fbe9b34b321df5c9d0fae6f3bbd23f7deb7e946f918b54df50be7df58642af9f2efd0ba9c77ac3d8d798a4be5e73693fd9d2ad0349a197fca25bf92151eca34b17924fad90fce9dda9307f5e29d4dbbb5b3255a0574a7479855e1fca8fdece9d0adeb79fbe4df5e5f497b349eb5bac1edd7ed565ec94b457b75fbb54a1bd5697d65ae74e052b4d16102b62a95bd7349722bdfa66a5953e54c4bdf422eda54b2bfd4dde5a692f7391ee945097d73a90949f4e74fb45afdaa59fec5288933dc64555181024b58938c41bb8a4e1f2a563301b4eb2b5cd8f3f76dec2167d53699bb3f43016515fa704e5d281e4dbc82c65e466fe9c7b7c9e5d5341f314a26b401d3f7efe583add629d6e754a4eaaf89bd72d949fdc86b18ff663cd6fd3be2bf1c3f8288fdf95f828d4dc6447295342f27394c83ff9e93af7b0c7d73ed49562fde4f1e39f9d906d80f5d355519fde79a03a7bb4dd628bba61ec51a72f5c40f49303c9f8b59f3efe2d72dca1ae907ce92759bf9e7ffb8539f10ac5d704f0dc2589ae916013a1093d3e50c41a32de5801c8dcc6bd31afdef0bc6733658c3ebe013c23ed8a463e7a7424ed527d748fbef361093ee7d7014fcaf4103e7c3eb3e50bf391d0e7b5d816394d05d46bae510fe70d613f3d3c35805df0daf5a2397fd4b56f0222ac21a609649f5ff8fa19569f1233e2ad87b0d79cf9046611429e6d81c117c5b7970abff142b2a9e9ebf5f26287c5ac6003d22b0b5fafdd707a787a19c23b77176034b8801cc2b76c35b68db99814c2dd4a815f43f39d64a6c3ecdb912880012bb04b8fdd01a6535740bb421f236e9cf976240c6857fc2e5242919dbbd3ad76ceb280244ba75dfcdc29892fe48546befd0be3b30349fe606fa45dd2db914846d3516c1c651eaad5ae0fa8699a650f15b74b5ab98152df98c80b61c8e3990e5a9e9f7f93dc6c578c6fdb253dfa3603eb8b58dfda3724c44ddf5e547ffa4639d91f734fd8ad405dc66fd7be9c25548a74eafc5ab72484a7de5d12fa492aad8fdcd360f4d82591dedd0aad9797b9a72f73a7c54623aaa6f3ce36bffbd4b99d51de1d03622290fd459403f5c6d1076f7394c72d852f3cb914ce37df505fb87d392a4c99ec3b9f2f9f3befafbf73a0ee2f7e17a23c4705d4a3ae906ae5bcc6fbacbce5ac1d79d2aaa5544e5946ba6d93e32e09c755759453dfbc2fc773fe30f69ea3be219f178a7fa5a8dff3d497e3f10d3ef5f56fcdf5271ff5b11d9ffae46f924b7df3b7cab1e5ac1a1f9f92af4af93639ce39532ad4c76da8be4e61753fdb2de9a92f769a4b41f9e621cab963404c049b739742f46ddb1ca8b7d92900e8998b84a8d829898e4225413950cb4e05946fbec54e49fc90e31ee93672ec38537de310de94ddf09d4bdf4e5f38ffe4b253c26464b2efee9010b391c9bee8e6552e6511f72a4f39772b58497d4342287c73cfc98bb44f85fd27efbea1941769af72ee9630517d4244be3df509a1f0917b4ebe45ae6b3f7d61fc9373c780d8f7652e72e2be930349a0066a76fb85d1b939aeeaf5ba759f5e56b73abe2a563b362b5e7466d6c6ce6ef908fd4ae89694e27d42d64b8f2e7fac4b6fc99f9374237cc4b94773e9a7cffb6cf3686ee50fab793497cee2e0a587decb2d5a3e2ce1a573c047e24ba7fcb49f675bb0006a8e2bcea3c72e677afcfe9ce93cdba2c5731936ce3c159a5fe737bbc5dcc33ca3dd6cb6e829f00bc5a64f8c0db23cab59cfb3243264921bcfea567749d8e3f36ccb16cf129adf5d12a1d8f427ee69ef2e854f76ecf18bcf9f506cfa78a7e59e7621543c9e25b5f9907beec447b8ddf211d4f32c498ed5f32c4bd2b3ba957a9e6519e2595376649a6ac9838c529b1f17c99fd38be44725d18562f4f931baf4788be2cf18c1d8b68d3bc9bed14ffba678d4999d4ea0fd86b1970e0365974456607adf570c7c496fb05f31303a7749647ba85d6a7d8ac7cf2d449ff7050391c008a1f09a47907ef26a5f289f7a7fd38124fdf8e7d720772d48303a504b0663121663111667ef50e91d7346ead1e99c13298e9f734e3a719e674826f89b67329620e343cf83d03cb4ec35c7c8fa79a76724b9b05c404869708b3f5c012199c13cfce1e9db23ff002189611efe7620ece26f34df7da3a7f340cd3b518b91051bef8473e97d8b30cfb32ce4f8b0bf9dd53ccfb448f3cd47e20f094d80ba7516ac766da06e35ebb576b15ce852989646af4c923c128d64926b249bd9b74b1f129a80e6d459a0cedd04722640bd7abd36684e6f4e74ea3190c11c16aa9f9c41ee845838257d3b0418ac57d682e6392c287dfb2b36bf7c3b0ce4ae859c7859e836ddc63a77157869b2cdb7cbdb6d244fbbbd5226793aec364c69ac4b97d6ad1a344cdfbe3597564afafed25d9acb771af9b3e6db231ac9d32e6fce04a453a7d706ebf2b2f97606190ca39a34df0bcc04e21c5a94918138f80b265d26a317261d07d9860c7e908116a82393fc895d28abd1dcde9c074490254fd8b29e3301ebd5ed8d4c92a7bdfa68bc865e963c6154fa0ef3d1c338fbf6f9c5302684f18b8f73e9f903188dd3aeb1e5b0d01e3d06f24e28959ebd3f963cf163c913fab3c3e08531ccb3b3371bf9c3679c402393c9643780ec91893dcee40f83ec318cfcb94123c41b32701626450609ca7059fa728488325f6632306ca5ee9274c21957ccc0b065b10d1b0194000f3796646018d73c4735610c2379d8c3665aa3264da379064399f4ecbcc3578a547afe00d6b1d88d8220485200410a0208d20ddef3ec88062917b0cc08b18283e732b074f163c170ca96df6c9e5e80d73d9be142cdcf67335ccc001663dd5108141f4dd0c0880630d0230e3064a53ef45aa4550f0814bad0830463cc800d355b80d46dbbbaa7ee69393242524a291de38c0f4f69ad9aa679d5eaec2887d5b3183dc87865b4fe897571c5124b286863031b4c0186f699fbd07b664917a89631636662f448a222c5b260c9c2056bb2c8e00928b6328c92c8a0420cea7966c407955ccc9ddef11ac9c04207a4ae3eaf576375ae0ed49efc611da33786703e12b51bc64dfbac063c4dfe7892277a74e79eb29eceb270e2a9cffe8932994c8604d2a7379cb2f3d43d0d78fcd1f97a38dbb3983c92f8eeb90ca3127ce8f9d4d2b2bb77d8dad9b7f90d0911c57ad8af44d9f3179e86ac17c9a765dac8a2d54699149c6990abf6d58feb56fb05bceaa1fd960ed45ebbe40d53e017aa3ffd74a7f765ae5df5daad39edf45d913f6f38dd5ea1aac4be506c7acd37ed0ba76b439a17c94f22a536a05e29da15aad33b15ec2b99eda2f78a7c79db278ccdeb1f963cd243d6b34767b780d72ee78f376ff4e2777461d33e7eef9aab5ffb16bbe8dbe4d893d3a557975d92aa6d1ae56697247a77d36597447ad4bef8b1090ac4dfc18c174956287537572a7dce39e79c734e9e5ffca6507d7aa54cff42e944b19fce9d92e9d237fb85d6514e5dbba1b5b56a1aa5734ad9af79d82ad43f395fed0b236b1e1d480ad5475d29dae90ba913c594681ebfd0fac9b7d317c9782854a3ac73371da8515f77494ed17efc1bed929c66a700fed31737d9a9603dde50ca74e956caf4f859fb49d19cfa36391bbbe9dc69f49b369e623ddad8e56deccd6e699ee4d19cad4febd2c339adcf15ac4b998ed32d6d32fff8481ecde70da97bddd2a887de12d54ba13e9d5ecd997f58f230ffb8e4d1bc6f48bd7da31fab5b9af7e7754bf3f9e1744bf30978def387de6bbec56e89eaa7e3d08f5f7649fa466f7a770ae09f11bca1bfbdb65b9ae603a6bde93ee7959e51cf24e085eeed0a7d76da15f2ec35d7bc457d7a58e43567cfba8f758d7942fbf6b66704663a928360a8d71bda0f7d5e73ded1ae149e4d2ea66fecd1163ceade33194868f1fc233d6ca7bef5f7b1f64dfbdd92fa52dab53b6dbbfa86f3359fceec6a0fb56bbb359ddef9fcd3fb636ef59cce3b338a8ddb157100433be5cf0b8c355a3c11821a9cc00ed447f7a2b3da653f721779d8e209dc11928de50f972088337c2c31051439740143eb3a7de87de8d3df923f1364e70a54977604b681040a948e00234711768b2f7cfa46bfead1a903758c377afd5cdb8738af79153167a4e162044a74e851cd600943c6092854cf649ab8e3b9e799511a2ab7d898575ca8f3d155cf678ef8e1593a1b471ebc762ea9012c10c28a1bc0e8a103111a993052cf66c82c35a58067bf7a0fd4dcdfcef695b4d73e40260a254e53743b2ca00c28ce90c1c509ba70810720e00209ad6a292eb06c51077503b5b1cbdb54b45acf0833b966ec92c813149a76c56bd6a96f965a6a6ff47a43adb58a5106135f9d55350a2bc11c6248d0c61b6b9c009c437ee2f1c4ff8c1eeb811aa8bd6731c8e043a349120805cce1059b17ec91658714e86cd1c66c8b156cc1f4dbf3181388317b099b8303c2a0c28e366d666bac20e74c0e3bace0ed33938c8e4a291b95d699c50954cfb32ccab046a72f6c7c99238c1e511021240b1164f1c39698105968c9a20f14d8800813747046e6258b2e1ad219248cce1c2df1e49ec7c8a18467668b2c5948f1014a359a45970f3dd7c28443192c419ec52863cbcfe759163f6461344617633c6b8e284224401932253023090b3e8c3e789e61c1c677cf332ccef0a423b973649e78e5043676193d475e25fdd2f9cc962ffdec4612d03f560d4ebb7886c50c4de82386186f80f0a1f7ad6e26c6cc870f91843bcf2e3b3eca33e2996dd7698bdc9d8a373279683accc6fe45a6f94dee91378cc5253c9e2d7df1738e19438b6785b14936cfd17b85d3ad1ccd79e645162f3d47bb4afa358fcf45d03c7b05a0f48f9c95d02e36a305d3fb3093d19469a1e6434663c4b1c9c2cc87dc468b0160d4d12d7efa31000c39bac52f3f0680c1a65ba1dd6917eb990160ecd12d7ea06ecdc7e956bc5e2cc3b39e512f81e1d915685c81c6b373edfac16c70604af36cc68c377e00cf6698befca6f2e487d33cedade185566e3276a7987bac97e825c9c1e8cec416cbf0aa6704a665dcd934232407b94d2012299033ed47b7915e1c36de9180c7e23c9c97ac4b3d2330d1911c04d3ce64bafc4e28e956fa0ad2255fc91a7b648d4ac9ccacb194ac49596dadf2ea744b7afbe90bfda5c76dfc85cc6e3dacceecd5a3947ab95b548bfc853164d698bdd6f00b8be8b3dba38dd9c51eb6b34bbfb47dded971baa6ece6f6d8edede2ef84beb23b36a36c628b2de5a449a6d625b15ced6c97645e1b299301c1cc48998b6460c74ad1eb4cd9795ac2cb22dd921a1210ccc4d13eafce59c4c72773da14243f59da67bb252fb5947a811901c1c4c8499f9746bce95bec9214759279a317d80e08867ab733e5ca0a77be4eeeb3ddaad716d19f2e377ac326a16becfcfae921ab883e95de7346a629e9f3a547ef74a09e62e4466d2b21f4a218cd6ba86955d3a6b4d427a545763e528d86f6d9e7a347315ebcf1d55781b867e5f40b99ccaf901849dd70e7538e3ac9cdc3e996dd73dba76e95773e3feb9df59c25f6a7db9f376749e7d33bebb653617a7743ea53ca743badb576ce6929dd4e74523aada5d35a4aa7b594d2ebdd4ab1ba959ad55a6b6d2a455394d254e538cb59cb59cbd994a75225a4be22dd5a796ba75b2b17c3456ee55be438e674bab5f293a77cfb4ed4765dd775965a4b29b594526b29a5d6da5b42b7363f7d2192df38cee3386b5bddda68a594d24a378ea31ca594729452ba853abfa5a0d1df24d753f66f1a4739ad5332e536e79cdc9cb5a5e56cdc2427e7e4e6b4b5d6bb39d7adcd398efb6d73ea5e0afc46b86772959b1ca51ca5945a0f29e528b573526a3da494a3d4ce49a9f590528e523be756b795776be5dc2e2e468ea3f5da6ead3cae72b7e5adbc7de54092fb6ebe700a93f9e92b5f6d2a3f7daa128a74ebe4aa2f34f227df3ace39a9941cc751ca7194524ab9fa75eba74ccd8e72da5651f674b2a8ba691ced664aaada8b2b4e951ac23d27a71ae5c29d3f791453b7ca719782e7299f9fd775db54514a29ed2e0957d42d392e4ace434a29e578f6f3ea746b3a4eb7a67b5fb8f393bba5bace3dd3e3186f525aa9576729b5d64a3dacb5d65a6badb5d6cdc35a6bdd28ad75f3b0d65a374a6bdd3cacb5d68dd229535f386547eb92506fcdcfbb758a958b633c763ae70cfd4fbe71cb49b51ad9a674b8e7e429d0bb6d72560fe79cb3d63a67f570ce396badd56bad97ffc6c916a86badb5d65a6badb5d65a6badb5d65a6badb5d65a6bad95d2f9d3298b7e5eb74ebeddd07ef5cd2d679d5d93ed744dd9b2a9a94f682943f1b9a9e92d45a16e5f58b96e9dbc4f7e0aa718f9e9a7934dc5ae39b94d143d691cb72b9c4e5dabdd3ac17329348af1d8bbbdda0fa7f3095efce9dc2daea99086d7be703e4f764d0f99afb78a556ae0d6ea70f050b628b28846568a2964d720dfee45a1e68be44b97958fc81399d99d41d9d0a488430a363329f29822690a20a6e832855214536431c518de146698e066053fa680c18f9b158e4fed638b2d9e4d51c7b71701a3a55b8f24043e32813cce872d7de88af7ec42fe57e4cf5ef6437e9bdcfc84fc46b9f9b19e83df2a37bf20bf596e7e3f7e3b71f3bbf90dc5cd6f84df366e7e3ebf71dcfcb8df3a6e7ea8df52dcfcb4df54dcfce86f1e37bff9db6abbe1e6d7bffd5879373f705277a8c87b11d8e7ecb976f195496cf1005ec8fa6eb5ab7558fa2ed238edfaf1ed5c519714709eb947092d4ac8e607d828d9f14a72609951216b2ec618bba9d072344fcf332aaa48aa5fbea9308242d1868a315484d1ba5021c74bf951d1061525e89e67549051bde7191535b05cfcaac0e184e2823a7344c4c6c58d08ae8a2caaa802e544c74532290e8d8a724f7b17f93c0373e6378f8b4b5644ca3db38a393e5a23b8e759152df8c947281f3973b4c5b3565cfcdadcd8e719981178aa54c76da893ad1a9db223af52374b6c29f0924c7b9e55d146b483a348ea9613d3b94d74667989c238e3d6b7472b947c7ac86d4246336fd87af6b0256fd8fae8ecad66892a61e1a5bc8d9f3c6434274f79d8fab0995437e4361fca3593cb54237f5e916de06e2b499ee6238d2e2b258f394781cd3697bebfacf16e779836df3d933c8de6c3d886d17c94711ebfac3cf41b0f593f3cf4709c250f4d8a6d3c990d51969494c4850b17c9c3d3dede5dba481e9eb6212a491e9ef62f1f36936d264fb2913faf11809eb7cb36408004910509e2ed3349fe70e02f96b7b7da9d9d75db3df973249b9a9a402c9b1fb55bf92307e85d9fe8f10b90200efb017aee39901bbfacee11100e562b5f9dfc74738f80b038b836dcdcf88d03b92c7954ae72963f3fee11078e85f3a3232c9b0371d6b5e1c70fffe11c5cc6b947388e85eb9cc1a3232c9b3378f44a220018e4dae05d1b38ce39c7f1ee8b4b5ebd9dfff8a29a2faef9be98e68bf1238abd155ef496d5e90d6dea86ad0fe51a6fef3eb9867bda63165e1865214d8ab21274a104112fa001134c4872e0a1c30c9a4029d10803832364797801d2cea38e276439c8a00059f258af1c83232c694ca0023040963c283f394d923fdcc685898f2fbaa0514a4387fc6935d7865e23061d607b51f350c8dae51af9f38aa08fe46947ddd09e6e68ed0dbd7a434fbb21cb27f4ef35dfeef31d3d946be8d22926611d3bcdd51e958d17b2b81597bc21cd51ce475de7a7944b6bfddad06ddea7d3766db09ccf6de3ae0d27951f7171c9138a5f99b8473a83479cbf920800aaae0d5beadac045ad8dd646fe74f7a8fba2b5913cd2b97bc431ddd0b77bb4cdf886acd33d3a3996ea47310c4b9ee9f386de875a9b7b641d4bbd3660894d2098e90c1ec5a5be61952d7943286f8f58783cfbb2d45f34344c5f78f665e951f1cb17f9f3c222613fc07a723f5516ebe4791fc62faf240280960f34200a6cc02f71c99bde378c42935e220f2b534fd81f7fb4c28b56786155d2da8455294dfcd21f56a6ca247fe217c923dd5acffb1256267f5955aa4c5589dff85043a3b5d1d090f0a126d3be6832ba44d3d0259c0fa71a9a34d5a03e9c5c66987072a11fca995c23bbc859b3915d98d8b4928ce94b2bb5f912c6363e5116da97697c42fb3262e1c52bbcf8ed61fc52d9c8d89cde121bef8492cbbfbc89923319f5c9c9cdde9794cd5aa6ba2febd55f72facb3a775fcda697acf86091dec95f29b97928d9f94b729ee4f28a685e1cb9b0f06aa56dd56a248f74edbe9a44361e9754ce9c949d662d9b713e27364b6c964e5e5bcde639839b87add4a971a61e7a290fd9535d4f5d8ba6e32e6bbb5e73395dcf5e161ad80fb05e0b6a97c17959f2b4e4f2fc014c158b8d3a63e39d30b27969abb37bf247737696fca1ceeef2673a3b16d9d404a29c7e58e4fceaf702e2f67b71e0b01f60f559fda5395204357f719974facb3a52b4fe924e4f543a0ac80f3528478a20ca5f40eecb08a90339304a420104e24811e4407a908b1441203837ca248f5473912288ba2f1fc9237d75ad481ee9a7fb6a2279a47b17298254baeabee24cf2484f5da408dafbf2248ff4ee4625c923bdde17779122a8dded462e9287a2e1a2b9e651a593877136d138ab719fea6ca83388f230aad19c41d485fd00a9873c3b5dd80f703a8315b4b27edae7499ee8f463499ee8f373c913d93c7f00c389c5ae68b60e1889519208603bd224227f900052478a600b914892381d46928433849124e97820efab7a120138466294d4034e47d2408ac348922a104692a40ac2489238e080912411613192a410c0be2fcd9308a03112232c154cf201db9124386fc748923ac54892502a469274e3319224212b46927441e9ec378c242900a0bc2fea4904a88c2489824892ba132349028262244943c08924090470de97f42402444692649b912479929124b126234972dacece8ca4ef6b3aec07586b6b5abd2c4ab5ebc9fb4a2200281d8bbc56f2444f2200f8fa21e585fd00930800f675981627d3a6e29ee82a3ec21e77423afbf68da5f3279db87c7bb80a69976f0f3b78f6c83f94973c7f79e327143d2e7957ea0b45d90b11c51e001ec61e009728a44adff1a9175f801186084270722c138b2cb4d8828b305d5051c592155780612475facbb13cc1488cb0a8c0241fb03a9217469234bf3092240e0a46928413052349d291829124ed80533092a422e0bcafa412c0ea58a8128c24c92ec148923c26184912ab094692e44e3092a41658bd9d2a31927a5ff4e6800278baaf974cbb39a000dafb8a4d312607f095030ae0bcaf1a8e42906445992c9ac0570e2880f5be607018c146972f697c008d903850cbf1ce5f4bdf9e84035a8d6a3a9e6a9fd119c459fe0a42fd474433c457edcd0fbc9efc05a685eb1ff8ebf3cbc6fd9b44dcd574e044fce58177e02f5973a9a71d070188108fb21bc799ddf82b0907acae62354adf1c388acb3708f775f29dcbc207f70574efcbca37ddef2b12b92fefe0bea407b759f7e51384fa8ffb8a68865ccfd33c755f2c79da756e9cc59c8b5404b4ee633de4191b2b84e51dacfc14c4d17ca7dc93b394bf94bebdeba51f6eb928452e1ddcd7c959377201725f5186735f7d735f4845c0eaaafb8a6c9ab4d294717025174623d34e41701c08e7da8dbfc0b4b039e72f34df28df66df2747351b959f94961ac87d698e737b755feddd979ca5ee2b2abd7ae935b9fcb8522972a1dacd7d8169c1f395bf5e605ad0dcfa2ba90430a5a1f9f61798163aa752aeeecbba7725775f72bbaf39933ceda8fb6a36a7fb9a4aaa2b971a0d97008c3c66d3de97111207a6ee0b4c0bd6a7bfa69a6f4f2a019cf765ef542379daa76bf735e97dcd25c9d3de5d29d5687a8c81071a5a98b9014dece20227e058c34b8575195958d1431a7b1401ce3bd9489ef670aa598ab388c693bdcb923c3091db506e84c402ad1b9d1cc98b49f0917885b8e96912dcf351247884f6eda347f008eda88f1ac123b4db8f16c123b4d78f12c123681eb21a2eb249a65da3241d217884f62080b08ee420fd61073c5d2cb2a909d43c8c4a4a5ca851520b34423202521e7884f61d5a20ddc202eda51ef6526d6aea03056b942942695ea3a4124023eb4846409a038fd08ec4815aa687924d9ce3046cb8200926364006ab57120871822e723863062083f562a94d4d4df61a21f98014a905d2231ea1dd08c9416ac423b463513535353581d5c3c9e6dba94cfed4cbcc135d63b1a8e7c99f7999a9ec9b0817890ed47476632d759a6066c95bc2b414cfea169bc1c3cbb3987bf83614f4f9cc91145772f82e20f6ecaf084e41147b7630df96376294fe812d12e171f267858f893be61b5ede30ca9ee57765febccc92bdf9e51783e011d8b96bb5ab07233cb6a9bc85a43627eca5e6829f57483635d9d33c5d2af686d6a7c4ac60f3dab51eca1b271a3cbcbd5e36d887d1a546c50046b3d768784985d1e0f29a871df8a95d16be8421c21a63260f675ee779c603156f0458bdc882b86105963864d3a317d9902d4efca034048252154cb2222bfcc67b9189b0c618d9150318cd68e8c06bee05077e03ac57c66f807c5fec302a482881821bf690c9407a654632999597f393de1d771358b1c08d27fac0d2d404b202705ede58536db6359797de5f073c299a87f0a176a3966e6909e223433eef853dc630f0e8cc775e23a41e707ad20f504bbb705eba901b335e38e5a3966e49f779010b463336e18551cb4b0ff9052ffdc5ee499e18c87618c145125c2ca991c9c0e9d1c1f8c9a6143b3081c312608046483d60f4a41fa0115283d4930e00469f5fd201c0179816a2bf58903cd2239a973efd05a605eaf3be80248f747a5f605a981eefcb258ff4797d58f2cc66d14346c377e460869719b011050b48709386c7602c6030d1cdba786372608929420893184895524a291a699e7a5d3800c797357cccc1061e6a9851868f3a6655050238667830d95184d2991e98d050aa2235040c9a18c10e6a34318322e828e38c3cd0c8814b1e3698a34b155a42e082199051c6066da0a00429a630be6c9402e08c399e6a5563f9d0022d4c42907982892d7180da18678871460ab6e7d919613cea15617b6ab33396680f750c1952209d7184111bbbbc19e64b89de1e726fe7d65fe823fd011d18c1185cf4610796299000e59807eafe427f80124fd4c146892560e0051912be00c38b1d6e8c4972038c62f0c091a629cb166bdc71c7988f11a86bb0b1fc89456102234e900409e6104305e0875e5bc09b5a652f5e55d8c1440e67d4c8010d48cfa439d302aa85524addfbe2a956b5d49630e4d0220f3a9ad0e28a3c503853e6358d4e9e3f9e6767b8f0e699a49c38ce70b1f54c119c36abd5a29a7367ce3967cb5bb3334649eebed3c187eea3d523b6d422e60bd4c8420935ec10019b03c4314b93447786f019c1d20bee28c3861347063083c677cccc3e741f4b8fa89a992e72a89a36a7992c7e4ecfc3999979e243cfa98c9aa69949e2354da393e7cdf3cccc166f3617d7e88c6f7cf570e60c0577a02e0e0f4b8c4962cac368cc1b4e8015c9d7190b76f070b8e799991b3ef45c9b410c29a307e5410c1274e0c103164b88618313e888635646062cd8a1a50e52b6e822823034780304761c21c389323faae7591919507904eab90c116a4ecf6588f8522449cc1a622ce5208b020c5905f8d06b51124160182dc5a08f1b3ca1861132982002e7b9cc1075d823f24891507d197bee92347d2cc61936eef9c7084cd88e253681394a2c51ec8b84ea4f8f7dec439ce790fbd0c3400864c858a2069f7a26238a366590002208109e6766e431a3a3368dd669e7696e73439da8a59552aad1498418a4133ca5744e54ec3c3c49399cef7843d6649e293b672f721e5a9487ac9f29a7cea9db5dfee16e68b71b7aa89fd82f1d84672f5a109ef9a77a38e4a58740dec3eea553fed15c9eacb59e17b2a847ef2e49bcd1f3e9938fc4107411c49897203c50c7286cc6a4a463a29f7c3b7da818bd192fca99e9b35b6fb2583f43fad1d1d089c3193d90f9e97c9ab1536c2b3676b14bea60051268da15e39ced8a71cad9ea563c9d6c956d4356f5d0d33cde8e2ea3d728a34ba7dff46f296577bbad33195b4a295bca96cc925936f709edcccccccc5da627a594777a46609a4b609726a5579f6e5dedce3bab87734e7963471959ddbab267cf3a2947ab6fb5efec566be114eea7cb3ec26b9fd7da58b17893721965a4c1014c1c722851059924ec40e3470e302b30a37b36c38b15501906cb1035fa59cc0acc88decef34570a2872052cf657821cb21007c0ce1c1f3cc8c14bc7d26c34b1bdd1a62a3fe44b4e9410ca6d0b41b16f976a9338b41d20d773ebed72e172b7e1c688af84c243666b1a61781591c697e3e8b7123054018b11a3250e30839b8e03003374c10a3a60f2627ce7cf75c460835cc40335d32c73a2ea0d22cb0336ef0c308c6600107094a48220b1a387059bac876389325cc77cf6770c872a21355cf20257db55feb69d2e9f4ce69a75647206b3ddd2db5c6b8b8028c2eea18130513196025c0d77a06872c5fa9a73dcfe260fad07d2c4d220001f031c30b11d25b3bbec3a769a7193efcc4f9d9dc9a739e2c9d2c7f4cf8410a32b3338cc450034e127ece9919627ed2cab4871094ce39674c2ff8290438e7a473e7e67956c71d0fe479c684e643f7f1418c8ccbd2921819cffa40f3a10d27d3ecdbaddd6919366666962da594524a3a392aa594724a249a5a45f890e343161f6fb436d58cb2a318e6c93c7522eb79f28c38dd62d722ed295b52e954f3f08428a99cde8d72768b7dca3965649ecc539b94755beb2cb2cb61a13aff86ba464846c0ea4916dc4e75bb28afdfc95a7979a513e069b784e17879bde4507ff10caca17a0d279fae29db27206b9f3087e23b75cf91978593d30b010627800253ca3d3c23bb985b38383f24ab93bc90c5ea83e9db755aac752db40c3cf9263f76faa9209d6f185fde240b9ebc5de3a845ebe5742b4bf2d0f0726a9a66af94a27e79afc89ffee36bb724849fd74b0dd5a76bca964d4d53ce199f9b9ac0ca3c99a797eadc4d0005eec975c05a3d7be8fde9f927320f7bbce17476ffb984c84be91cbce8349c969373ce088b313a85a861dbd836f6d82f334bd9f16d25619fdbe4689784af4d42bb14e26fac4d4d931d35ed948a2ad8a856edc9f2ac4d5c5ad34a692417eb95676de2d29a564ad354ab5a9bb8b4a6959a6a94676de2d29aa673d6262eb5cb90676d9a7d5335529cf194921da5ec4fc66c3c5db1f18eed16373d94720252e43c3a3a3a3a3a3a3af2a4576b53d32747398dab9cd29a5e6a338b496de449dff86453b383008356f2781f168f3db4329cfc0cb6cb34df524d65639b2b58233aad22484e1acab27929dd4a77efe338a04609c056f9c39292e778d92fa5e34867c9d3b5ac22524a29a54f2b7a8b0ab1d18308227ee0d2051e23b0a67bbb04f0d35b33f8e9457c7e93811837e010e3061c62dc88018b71030eed2b163e282d5a190cd14d3fa1ea8783a39dacd6039b808c973b9a906e7087123e32c8419bfc03caf2e401cc0d468411c10b982001132270614ad72c3da54f6bd5e187a538a29042090723a818401c484fa7c6c445ab370dadcef2dc052098def2dff1d6d4f1944a4ae9fd4002c29019838e229e80410ac09ea7eeb1e4783a6fcbcf182991c59d52336bf4784a29d5aaa6e1b89919ec70e4a867337194f9eed90c1c6458950f3e9c4579e8edf195fb2aad73d65aa62fdb17c6b7a86f6787a52a740853461a476bf6006b91af5090f93aa60a147cbd2d3ab6d8664ab2d6933fce821dacb77ca75546186b5dfe7863a4e171f5c86043461b6e17dda2450af2f0620b1948d1c40f02c0c30c1c6468dad7f21df79d76596da75bb19e39228d967bcb63f94e1bee833aa9e08c1623701883298b9067a62f29d0c850813a8db1741a238ca765c818452461460e316e20e304c7c6926349175075ab271f994c8665ccac6adb455d16638fe661a3e6e10fed6b64b4348fc6edb23b1031f10226bab8c18b2a640120d345e9ebc9a9673f1c6bbd7651b71ea751ad3370e3cc192c61e810054f0b709891f901684c180e9ec56099c24f748724a42d5bbcd882060a2ed6b4c8b8d1830e2a58020e2dd0387334440871e4717a3643860e4124a19034471a38c4e185154000a0e906deb39931d2e041274d135288e0a88d29ba00410b003ccfc6c82ae0563b2179764d9fa5a96d4fa7d3b56d28ad629cb1c3d7b8d57a594cb33295bf562031a793fd70ba5a6bddf93a13c3e5eb9349923cfc738a91293d7d162346970f3daf5a0e22b801298c1b20d9e7d918b33337acc112061e4662f288028b8703051e5f9fc944a1c6879e6b916da24be61ea6eac546a59451065e3f6f5a52585bd429f532cf4e7da75d1f3c751be6a973ed6a30983ef49edaa7f4037fa678427c7633f8488ceddd37a670f3b1cccdd3d6344d63ee899a6b37d4b41b99b8a7e916720eaf3d0c367f53c68b68de670023dce173c421470d5278c136aba8827ba41f218a69708ff44805f748a7cef40ac588868f4c347cc6cf1bd1708f0cbc9b47134f20011fe1974c1fc63430f0dc883f405f848079f8a57374017d3126c2e0e316cf1fde7c18d3bcf498a65d405f64c12d7ee9b18d7802d0176158047e258e8b8de391273db43cf302cdcfd9b37967c2b0498f5ed27c647ac9f49129cae1f12c0c354f061d6b3eac3f0b230debfb997e492c43ded92511da79a38f4fbc506c8a2f99e209fcec30f0d8a3173e42148d3e7ae11ef623444f7cb1e623d30bc5a6ae01b10c25f189c8c44788a633f74897654433f84864e21e7633b8873d96e123d1d9f988bc423e9336dee9e939cdcdd3aef8535d7a1123096857b43a2f9b873ddcf1d0e7e7e4211216337d374fbb46e78e84c9d8ec68828dfb796e2e7f8638bb02acc89f2ef247c723cad981e4cfc9d963903f0170f6c845feb87fa0727623f227e5ec4de48f07ce1e93e40fe7ec7149fe8080e3ec3ef2e787b35740fedc387b94c99f109c3defc059cece82fc21e2ec34c89f20ce1e95e4cf157243fb42bc3f1d1e6f39009c7e43ee518e0f71edfb60c73ff0cfebe7f7480380f3b8fd02708f9a7a007cfb40b847207cbee3dde741afbe106e08ae79cb817cf71e7d701d04e7e023728f0200c4ad77f01d1d11711d9f79f1e585384e11d003223ec455df11919b4500e051e7443cc75139374b0a74d7b9471db8ca87dc2c40c0a3ea39ced2711c47f98fef4807c787786a88a71ce76691e0110747436e961ef068e543528ef2f91da56e160380479b1341dd2c3ae011ca735ce766c1018f747cfacd7704c4de2c1d8047d673bc6f160b1ee978bb0cc0cd12c1231c1fe2406e160d3c4a3911a737cb0d7804c4551ee43be2b95972c0231da7ad9b65073c62b9ca4370ee3b0ae16641814737dacda2028f3827e200b8598c80479ae7b8f71d61398a8120dc2c2180473a2efdbb5978c0a320ae3af9e7d7e377b473b33478e4f910c77214033fb8590e001ea99cc83d3ae1f80fbff1957b9e258244fcde2c3fe0d1c973ee518e6789e0e7df91ce3dca12411d2782f2937b740fbea31f3ee41ee974e02ce7c0833810cf12c19c7b747474a4f29477cef9e64052c8079b7d071feb6b491e760e3e16240f7b908f06c9c30ee48b4a92871de7b39287fdc7e72379d86fbe0a481ef6d517659287ddfbe217c9c3aefa3cc9c39efa8c481ef6ee6b2279d8b92f26491ef6ed8b4b92871df5b1240ffbe903923cecf68b41f2b0d72f72913cecda17c3481e76fab9e4619f9f02240fbbfcac481ef6fe6217c933933cec302f16611d480b458b8f10792013da5c08e5422717b22e545d487321ea424415cd4b27e2d94f4f3214b9a1ed868ef221d40d754e3e74ba21cbfa90bd214ef5a17a434ff321ed861cf5213a249d0b93eab82d4c9854c76d61c2a8419d6c55a30675b2558d1ad4c9563561521db7850993baa1ed6ee87137646d61bec3c830920bea64abe482ba272b6f5d83b26bbebdae29329bcd66b3ee52d3b4f5428f45bbcbb74f36df5db61bc67e2bf26cd8b061c386e9db231b26262626a6c81495a252548a4a34b469d3a64d1b1628a361342dabb5662b6cbd46a70bbce833493bddd0a3ac9f33e90d4faaa137f458cf9252cd77ac8b05486aaf65aa65d72de5ecee03e41c09e553debe2f98e69aaba4f7a40e3bb975769d9e563aece494d5de8e144198e6b3ba950e43e14c6f8759d736a7d5612897ceeedda8a6f57618756d75f2eab0edc6836dbe398cf5e092424281dded3c7f21a1c0d4c54204e5b0d3b692ae4d87516f4f1202aafce527876d5e1d09057a170b91d47d9daab77598f4e94942c08ebbdb65d4c927755875eb2f18758abad35fb0d3b5d661d5a78555ed05a31326fb7a9bb08a3504db940778e578921050ded7f41792064a172202ab6980f2be9052a0f4a420e0148a93625135250901a5bfb0104142d179b11079c13a0f922404148273e3a5b615a7d2c10972e3a5b61faa152bc80d8e97da80ac7ee004c1f16eecd47e00f18604c1b949398c734f673b55ea30cda59721391d388b3a8b75b110f117cca2723ae8c05f30d4b4ac0717504748109c1b6f7318e7297f21a1c09c8b854853531328a403d67d25090139b82f18ca83e0dc78a9ed54a9c33897fe82590f8273e3a5b6937418e7d55fb0e94170fc0503e237fe82fd70cf5fb095a7fc0553f9e62f58e7d5619c9ffc05d33cc8dd01723d9ceb3f2ececdd5595d967759aaab93ba38dddd7118777dbb1eeaf2e972f6ce36217abdb64d687fc1b4cbb50926b4c3e6b56d427479679bd0ce0ecb8927a68da7f4a655b316754a393bb771292fea95e72a1c67c749fd0d8e1769ffc38b82bc908ac53d101fba329f032f9a1fc48b705e0885cf192aba79960f15a1be031fbaa27d8e17f50b191a2af2de031f2ab23fc475bc88f542f2890c15a57ee84a3f91dbeec127b927fa906f724f749d8f724ff49cefc43dd1857c967ba277f055ee89cefa34ee89cec1c7714ff420dfc63dd1817c28ee898ef3fdf852dc13fde6ebb827faeaf3b827baf7adbe1bee899efa82704ff4ee03c23dd1b90f877ba26fdf0fee898efa3ae09ee8a78fc53dd1edc701f744af9f0ef744d7be1cee894e3f21dc137d7e43b827bafc3c20c23dd1631e44d966e37611699a0b1121a2d485884e279413715ce7442a95e74437373f9c9dd52e22298138bb4ebb888204e1c0d9bd5d442c178a4ec472a10eae94212121254a84a20be1b89074a1950ba55c68fae64b882c894d4d4d44ed42b16f28149bae08f90e6ec8ba424442e7e08641747080dc50e2dc90b5fa71c39bd50d7152de0d55a91b7a9b5f11f2dd0db92b448443ddf07445c84fbf22e4ed0d79f6e115215f6f58d378ed0a11a15788c80daf087979c329358d971e16692fef9520df77c763ac38bb98433ef4340a543a4495d91e52e831440dbeb0b9588831e9a494f361f5850996c0c20a30d650f19999c30561823ccfc21071a25a6aedaf93d61a46f6b5d67a9abe9d3ed6c943ef4fb5d6ea5c83afa9af5eeb29bac5c2871a2ccf82dcf398313c3c7d1e3386cd879ed7936f9aa6b96bd4c696e8e30d304d6a00512607d77252420a204ee0060e3cbca0871510614ae344a9089ea2b430c1962e661fb23e7afc68a68ba58f31ba085e7b64d4a9c8b35b0fb99fdef4e9a8d3e94e9db0f5734ef758e0acd7ef126779316275eb328b25ed4b29e5d64438db0c1e4a434be2e74c9f3f7d89f6f34a6133783011a1ada874a9574a44490d42c710a21192d1248002e315004030241a8e86f3400ef4f00314801086a858524417c8a228c851144651c618430021001800803186848886043412b71b6f028abe6f8458d9354aadc435a657d0da5cae46e81fcbb718ed3d60fe12f11cd33fb06031342429fca29fbda6ada9867e43f5594b93d124a5bcc71edafea7955d340b3a5b4a6ce0a97dc63a9376625447cb353552454c0a768e406694fef7e8d9581f1d6d970e0ecdc604aa4204b71408c4fa517bcc6ad1b325b827b2b20a70c55df1d1ed2044083986905d0d37f9c442dc26fcf1b7d94fe8f0baa75a009e839f4a5532d12cdddef5e2ff27bb4d785239bc37ccb5376c958e76815625294d2e77372ea890244abaf8d1fb305ea932e1d532c3012387fc1ed7b5b15efa01f6f95f14966f2f5a685dfea32e3114f22706dfac751c88b4c7c0fade7abf43d6d517168deec5b91547b84e1db8c4ce3c25a7f6d18c6bb39c55cdde95a96d8698566664169a320f188ce5960c668635c233ff510250afa3000e2f66395f00356eae80b54127434d93b1e00ac2632ad8e72cfd3ea58226ca482819c1043c9b2c95515067e91301094277fc8f50e6bb767d82759471842204eda88e095303c15500fb57c1e62e8b70c81f82b752144a40f2534d86b46b726742be29aca2fe1664a41c451ae03b500856bac220e7b0a062ad7939661a5690e9b5d98ae1d366fb01045691263f6b57ae4d68c7fe8a6ad166a385dc503074eb5ac5ec14651dd5b926eee1afdf1f936a3f7c4fe904d048a98371f1cc8df593433bf98a4591dea80ea247384fb5eb1afa1318b02caf64ef20199690e0e87aed9b018357cdeca13a2170476036386246558899c93a94a27624334437ddb39cd9f911a5db2288607d8dbacc30f4e72ca4d22075a4d64e2e9660353998510359173b1cf2680aa939feb2d16eb6e8c7eed14846868d5f1d5c79e377545e8a3226f984a7a779fcc4af6ab7c3273a83f5656c0deea7c03625fe6a214a1fe29114c53970dfac3f30f27870f1549b01a268c178d0a05ef0b9a44ab4d73c9b1f32da9dda54ab26f9cd650cc8398dd1fb3515d69db0d0cbea998ff07b16d7d5ff6728b9877de1874dc27a79603941bc9264ab4dd15648362ce20a661c0799cd4ddfd2f7af72aa08daea0978f40f7862eaab9fba0759cdb5f1c01d7d209ec112582c4981ea9bbfd277aed98fdc1d9e76c4b484d4e0027cffe78d585d1f4de36583a6c2b3f2956d2d698ecb15967ac3dbe3d478f3ac9ed498793986dd992355c6c5e5d0ed6d6a008798d56156cbb1fed468c149204708e0b46227dd1e517ba1b27e1ad1cea09208e485e59962e7c60a4a6bf98337621153354c742fed558fb55f3267260d8e998e180f20b4f9066531e5b3d3afa2c7aeec91152048f6e40fefca5c5330852916f82cde50989872f62081fa3093073b57e67caf2412d3d02859e2da0fb9d2cf9a785cf0c922ed106b01d397b7206bcddd51ed2325c89e2ecce8d89a735e29c572758ad0fbf8077985081f008f8602861eb2e356d8b74bab821cba3fdca4907de1642511642fb7a0f3de44ec516ccde1a09a0eca1ecdb357c0a25aa006ee0056d6385779009c6ee8434ec16b9b811e5fa03cff346733663b175b29f9278e8028e4e4eadc4543f1624e4531870b5809ee40edde853da3895e4d99ba3dff136aaa3dd28bf9d3e11ee4161874d48a61eeea9eadd318db848877f7cbfadff65be4c2678939be8e0b1accb9181a09d8ae8b860c2b0944966ff748ead3b5dc235956dc16df3df9d5db22dc430fb7daaccad2db1f162315ca12a90f7e735be1a2b1448c9c8f10ff1120c67f82e8b7c57fb18977a01e1e21f76bb11e1c20ce19b85be016159e3110393d950c8908ef84b210961425967667afc900c39d7e0b2c1b700bb162f031501feec83ee2d3fd0cd473d342f62f942ea1ee4c924b5f70ca03cc60c2218395219e7b28551f4997d9253cac05a89846791f06a3c8d60ee44431197700ae2de0304a24d6025181f642ac79205e39acdcc325a030ac124998de1cd554c16abfa40600ff5921c431c92ba5ee6cbab1fad59d29b8c6a6f1e6f9f7d871ece30c94227c6953edd9c214dc131145e71ad52d20e1fd89c6fa8f29c704ea9235be351554e0d32c26e5e92ec753a48f27bb6f4d0549ea32cfecac7c39098b247fd6720172994667bab87fe25706c253b3a02576ad27132bb8525de9ab8466f573410001874ac7e8848e1e908c383e52f7354e411f1d98db746641cbd0db24531d9277c867dd7e3155e0712c7a03d525c208339d12f65337a82b2d86d9a3450d663c7c2172ced312f9944d84478e0fb584aa73286197e3894ee5f4f9441d5dc3beb9236350a24e3c6bbb5896947d14dadc33cedd773a7da8520c240729d5d4f170f6cb1ddd5caf5b57e3c6ef48c8c591630279d17cedeb709572c087c6969ddd673602ab818474226c447223b532d49e5d891b4877a4a19c9e02e6fb37b1af3c2a4982344df036dcf678998d6e5ac62800dbb699fcb6cfea54bc3c0b04afabe984ed0e6c6ee967dde48248d3effc8b35ef5787f45c44122d7f6d490b9c56eaa087d3cfc4e8c0a92ae91b1b378cb6ac4f87c0e6c9c10167d6b6f42b25d40fa8a1c1249c4e16642aa6d01d401488adaa620e1df52d773df4e52c756fefc5a9adc395179ccac76d8dc508f60a457ca3618888ccd05290bf0c2c135981cc636ee98061fc22ca4fba5d0cea3570a4dda558ff0934cde2976e17593a3ad925b2296a778f3207fd8f738e325c6e732a61a4f23897ccac6955f04b471ea86fe8a7706d27bb6da82a11f2667ff5aa2189dc033975901cc86fa808184fe6e11d72d2cd78d3e51e800b7c3545adc32ed9262ea64ccadc42f6e790813721330624d7a79c78a66f15bb192d00c2098c20413ad7c02ef846add00a1cb7bdf75dd0ac9083c28652d12138f44e37bc6b43e9c6a87acc6e6f91e0815ac39418f4a4d297c2f7af09f60f3b014df02cb4e2e0a8376337488151a7a38232d703a1e4b65f86099edf03255e50ea0612c544d8a836201a429c233df4c68ee9fe38e560cf7740cb705c34fb0689c4a3b62be1fc51997c75c35b1b71840085058cb72f1a6d6839103fd774837219262732de86a0503304448a7c5aee038c00c0f4531f5b2586add2b9fee05c2dd705a874446878cadd98c55e0f12b492f7dbff4b43add1d81dfc44081804bf363d1c2f3dc572fbbee278464885058c51da05914d7243c5b7680572f829b7361db00a33e38221899e1cc6ff2195798ddb58f472faea2059f2a2ac81ff06845448b4d601b6d4b555bc650d31670828595be0f1ee256e31c8ad2889929ea8806ff71fa3cb364c541ec7f2b6635ef1a0f21cc3d5d638620da15b254a675a4efa7e5c4e6790bd04f5f21eafe5ad2ebe7cd817a34ac493e1b3d38f9569ab0541ec0503902cb41252e51be65c91d5cbfd4446c27d03072bea7f0594d5f20feb2600b28fe73ef9c38ec581feb5ab982bf1fd372b30eec8168d459b77693d01f6b0cbca463048208125f7bca73407a4a2977269b25629d286484b07f87e772cf1126c6245e28dd5dd22475e407250a612af74c2e4a3e5ab8ac4b56f78c25b5925b1d40ccf3f620fe72d5b044bdd61adf7865ab5ccc811078e797bdafb510103d0888ee492384dd29c7cdc0881f3f525af4c8c25fa565ed5ecb19d5f3291ad3999bfbff537bc362daf2698da88aeb169089f419cf8e86d3055710b552a4be2eea9160a3ab9b84fdf13e8b0c52248f2b6d319456586690148b67829a931195363ac9d633bd4ebeb0f87fc430fb85d6d0ba46f336a4a8f23e821bb122712bc71a96ad537b955cf609fd7f89bbec45df0913ac526980b4909558b9ea1b5fa5adbdb2985768636c28bebcb2d126c30770c41f1593a6b3215b20c0074b297218ba937be032ba70244b6c68231a89a9347919d2b9095d8b69a1a7a6a0324c6ceb27fb42fcacbfa3cf417a7df37a40c8bc2b7b58687e4f309ff9a74468006dfac9c9e5f8d0c0de97e26b6b547484e2a881118b138d8b9750b48c8ccc37dc55dbf9b2fcf69f815da874f59aa0c1a39caa48aa4f00e6360bc2cf971cfb41e14ca4ff7d4dce8c8f8e24a60947480d2104ce66f3f0501356738e5b131f9affc6a6725d36a11bedc91637af8fcd12f9f23225940837ffde864c43f6967600d4b0984341515262b2c4d82c649e309bb60cf5b24873f4abd4d4fd39e96550a1f0e86e1bb1988e95de6ddb38aeb01211699f07364f65b920812315b5d92282e3a965f5a88389097cc37d6711add8a0666b3f5b78617d984be5e0837ad96c91b42b21054b0030a654f59e23eacddeb05554e32d5998298cdc01a75ea4a035cb563dc948c54c333684889a1698214fb53c3f54e8004d5136e70a5f15d2c43730a2801e1696c64c1addc76794284fb29652d02ce3c8141dd1e6d32fc1c8ceeeaf34e9e27de3fa3b98554d45ce748db2daf2e9e4ab6d759191339d8a0b03d6ef61591b92fa4e6334944170352feaf3bdd6fa0d2b2372238f2d125a3bf7b57157b0cf4abe684f7c8d64925c87269b413df6f2566267225a9803ad5b8eb1a1b0ee234ee3f658114a7d3b8c0e9250406ca260e539607465d9e1247cc4a11c5afdf30c393e1597f50b064ba1505c8721e8746413c9f6b685f4ce81c1dfd1c821c218839ee50e215cbb3c80e22e43980cd43722ccd99ea3f0e86de50a7d604eaa979625a2d1f465d692c62fde682bbcbfcf18ae1e7d860745249737549b83a8bdf4c70faaf0c9d2778ca42b9ce737970c00599e40733bc46a49e559328f33b89aa76aca0bb557c9ce501f53b5f092dc2ac1dce13b6ab422bb7e0519b06a1afcdfa1818732912278e45b33152ac841e0c21984f30157c0ce80aa89aaac61611db2da83a5136d4b693203974aa8becc85bf238945365d9145656b36d37a78a03dea1cdd5c57cf0b55387557a8ec8350eebe9a18943f2e44af3f7a371263d007b6fc844a811fc64c779d35cd0cbe4ed1a73959ce7addd462696179547d30c60c01f8c475f7cd50a1b6834b02f033d5e08a6d928090424c5e92d541ea7ef62dfd2a629f25b29f4fab4297e1fa21fb714a1a9dc1835447d0951f5566cb00a0e3bebc19205bb262d303c1a0cfb7339236f1d2f3aaa8f6b561f9e253f453f2c2f0befbdc5b48e9fa694f65aae058e73c78feacbae01e537e25b400777e2bee2c3478b4153e79152dca8b1200d18610fd93f4abb5599399c0b88ce130cdfd1976c4fdd09e9f7eec3a05dc110cb930f49f62185a5046b1d3111876a6464cbfe799dfcfcf81ced3dd0108f4c6ccfda60fce09a703aaa6cd8dbd3d112f6f7454ac136ace6601f74b711dc13a5bf39a8ea88f3736a4156a7c91efeabeee34fd97cfec43a27e57a6143805b671aac117977c55fc988c2a096d6be499d22cb3d29e6e10e5e09bad3a820dae21c86867f1dd8d08f26eb25dc997ef5b318b930b249ed8c4e768020290b2191090379225de06f9a11f0d10b32a536af18f8f4e3e3f5c00a68911c6d2f660c4c92c518f3d0c03f265fcff2e330abc14f7bdbca99a861f8e2843a25362f9b1920106563910cb6fba01a62dfa6db32e81c805f2cc94aa405fd760a74783067248b7e7246360261ce9503d1d68e95308ca9cf6e7d60f5c1e5e0d46fbb94281746ddd2807eee46f5e096bc97c5affac56720298e869ebbf1eef8157e41cb93d0e587c6584378f9e0e0e4e5605d9683db9a83d136924eb8da8a6cf48041a067652b6e8afab34902f17081cb6c35336c4598eb1c2dc213cf28a09c6e096bea306e7676c3eef956b1f3a516fdadae9fc50741fc69c4b21efe240221a22ae29a203118e3b83f4e3c8d24f3309736216f6fb6cb4faa10b975c6adeb9d7d46b0cab7d7a6f947b1284a77434e1c1a7accc42a97f56d3494207d0601b3241d244b3e53d49560a02dbbb027db0bd146805cc4268fc5a4e928b6b8444aec1e7e5cae769709621fafc3a6be1216278c80785a95fabc97e819533aa0b861aa19fed700344bb09eb641e09fe35286cddc868c2d465bc662b218284d58de19f66f71b131ca602fc1bb9e53254ed9a0d7603c81be04b11a04a720e1d369ddd506ff913da2c4268b44d8a01d551f5b3d8b9b4970f7394396c450f8b7c915f380c79249a639920080247f785f9ee5d70404afe44d8c996566873225d33b76ee7ae74f9ee2f75ed0d172aea79ac8093b407e79116349ada86b31e4a89c3b1c758cb76d48b5d49b0ea61a5375dfaa4f4e17b64d2a3fafeb151d0098915d92d6e76770811b6cedbe2b47a3ddedc8e12424e75c2d0767384ce79e0d0f410a82effdde512ec2d5a672e875ee1a79fef06f1d81ac3c7551ae519394490e98ad22388f34d5bc6d7f395468bcf80942a481d755d766be56e7afa773a4eb64b2f555bafa1a4701771368892429386fab5c830d82d80fbc0ee6df903239f9860699655693e031dd9e6de5329929d4509fe6839329620241e217aad03dcdca726aa2352d9f0244b008943a96d4d231444a8c1838aabb10a4779b9bb790b2f85097fe9a733692911a2fcfd0a1ab62d7d6d1fa842fccb608a4e0414dd7771772c11a300c4ac0e468e0e438d0bac47ee5364fd005b6a3c92d2191258988eac2d1b174790b76a14425e61b8992499c196a4bb4c623c5d2d675e2cc71413a4dfa106f0156d0a2e90079883e7c6ce960570b37d83109e40b698e8918875de8b660633d81843ec1f1fd1674c3d1736373eef9a737582a2347f713abc1bbcff17489e2609e4b226b0b30436c49087dddac524bf77183b727a43f4ca84c55d1fce57184d25f31be5aa2ef0c09abcbd83c4b3d20be0ba9105326a472f36487662f298bc4149fba7bb9586b80b8dc588d027a3c9f6206629fb80c60dc5b5fdb59c4690e95d27ba754db729ec6ec4500cc01a46e4259e573509f1526ba07943d8a8c7243993693b56a6a0cb3c6b9dd6a40564193d8e20c27c5bfc1ce19a0ebf90a252e053e68425bee6e88346c5c86cd103b2c9ca2bc9e343e62edc4689df8791d29b12a9bce2fe3fc5240a64956ed72229ff42d7e162a419b9b6325c7bccf8dff26ee6ded478927ce31bf72a6a8610f6f933b4c5da9e5a6677eff5b4761917e1248e8b5f6b3f41594137550d9acce31c82e09afa9df58f5b625bd75115185a2fe6785d651afa61662540f7031f631a9f7043c02e8a150cf8de3bf22a0641827867845b4c0453951af41de4c45acf5274e62f59f1775cc8aa79609a556a61d7c5132b324ad61b0323f6e2264f6880e31e19ccfafc7849e5818aede8e2c7f882c24b0778f70dbbb7b735fc98e71fdff013701dc48cdfd07f063bbb1fddfa8f4020ae7e3ee1dad27eba25c9b668ff2e203b6d8eb4412bdf9132e18f2a9212c33946cf321ccebb3f2b40b8ca0f6990a434155c341b23f913fe1ff30f2b08b2f4870a7310a850107f4d0537d310a69379257e958bd70b7b25489592d898bcb12ea735cb991ac08077aefae29525662ed4a379133e06ec9d6c2218c0ddfdbbc32be2772a5d43309f724734b00719faa28a12fa2f68b5aa9a8684f62ef0fe6e6568ab65d9df9399797d23096944c36ce55007a75caa019b9786c82690def7e57954d45870f686d67b23cff2860be07dc3978bc08ee0fcdef7091d77e2fed1154e9b517af5e67c5c935ed697cf4812ab4ed77dd3ca2910669c210ff02c0802ed77d894c865b8a6ab7fd9719989d951d0867774ff8036df504d35e8f9e7f27702f0313788ec39b1c69a10064146f40cfc63a12d32ddb7bbb3f2291f2e2c7612da0ef68a4f3b38f0dbaa7c454bc395b065ea8975848037f73f07c6ce85e67490dfa8c1dd91e2c46c317a6e9a3036fb913c7c36be3f4f1d615d6f0b0f2ac894a15f79430de50efbc4001c0900f602f7d4c6a16d2fc214a1790e4838e8abbb0ca2c47eeddc7a1d70a1694178cfc08194c5d76e56aa1758f11a11f4b216c62ee06d29e2c1d4e2501c9b7d93d46da1896c4484b87b141942778d7ae4d12d5fe0b5c48c3de8ce9566a8b2235f9a3a6c6b9835225a4c6656ec7acc77d2f63e15d5d2869e880a484795dfbede11804732da4b83d2e25b3484c87c485ad33d54e0f67d717f6a2a37dc2a82fe0f976a2a084fcc46b8d8d0cb2337fbb769fc7b4bc45940e3aae9bbd16878cf000ba80ad4733960a3eedcc086a5b911181415aba66405dbc7583b8115c82add0583af011366ced65b143c7b78b6aafb4deaf4e0575b23d6bc1e353315068a70e83df3482de5e47b9693484826c0390109e1a364e82b16e08fee09b49fdefce2a36f4fa24975188f4145cb4553c7cdd4397b29c87a63fd90c89a10c369ee218be9713f3089257265137b8c989698cdaf141b94464e1e809b52d37fa7c341997567a1ce91569def28a33f5adb83201f81c1a6aa4510a0e3513540359a82ac226dcceb50859417f6631cc7676f2f8f22d218a519bad6adb118b533d3fd48b62ddec2d7148488e1934bf816b5ed4b7e79a732e2430aafa662350ea007e81c35a5ac1bb0e3675d556dab05f802900a9685ec008c22e8deac2c12ddd9779899e9e296f7d84c7d9a392654effb8b108b79d0d56f846060f90f92fbb99b1b991607177c5c5407cd7e86b5e09f664dd8679d4e1ffdd9f88b0ecf18daf016d1a4748f203dfc2ad6bcfc529b0ff6e93bff1838f633b0e8b2db88dbb23747723df0fec76995c05ab9f290c4ecfbac1e0fa79da143f01e221dab14ee9756e77696166ce0d65c68f84a4da04db66c4dc5091c261b4207326babb76667a8a2e2b32232d48ee32a7f9fdd2d9180ff0f71058014a239c6665825438e6244c8418e462cc38ccd0ccc9fee7aabf517eb7b16c63f0b1d75516318f477f9e194445e6a8a00e24af0a7d8ba91f4ed8f8fe15077d89d754651902d447e9575a5227366d68c788c40ce95963df010025215d4eb7e887c3447b762c0385a0539ba0a8e43fd26217db89705be82754e313478c1f1fc3da891bf6f2acd32837d9f7460ecad53838ed28455f01a4c48eaad9bbea19636a90833ab357ae8956af3e8ef77372a40e0bad3d3bc217278f6d189f84f83b614efd303767ab54e0e53eca68281cd335b314b64e55af25e8414e38d59c8c9d56d9503ff02f7f5692ac25f1081b9d2a61be73cc834197eae1d77f7c374e30d85da85bd02bd8f500b45740d3499dc050e313cc4a7157c411e4588090ebfa56f7fceaeb1043ef45811cd043b062f00dc5e0ee85bc89b3434f76786c904bb9682cfaf45fb501fbf13391d234191ffce3abd37e0edb0e3108539a08dce9bb02ffa3815d15e639946da543e110a2211195b5fddb756099a920afb0ef3cc38f4e0ad484d8c61e37a65dbc5a85eb55fe08a4d5f95ba9e5723b5cf50f2174ddcda428386f3b932b936f9ae3baba7a0013784e5b9dfc8ef4fa49905961dc98a58c8739bfd4b92c0e8c578e6b8b42af08c0a49b23cf21c89f8d910396094fbba25fc25c1cc6b9361319cdce3def18ea79098248ee50eeb20928f408f30257fd074b9c186ab86075ad98c46b84b8e3e6d2e2f44d3496ee95ec19a06bd1eb458875c6d65eb781d728caf1e30987f9dd025ac81ddc1c8fb5edc27ed97e4e0199f2a2f1fb9a9ab04b1708871baf52eef9c31ec51e8de8619be72a14fdfa7110824da2dd1b22bd852f3adfbbf6cea930d85a95183c45dfbb9270685b35bef9718bfa516ee32e3b7063f2a58e15383b370406898060bed50252e80c6b3ec742e65314eec7166120ca9f8dbcad08f7d0c1bab25931341c5326b89fff0dbc4ab7da4a78c25a175c3bd5f658de3af8160d7d570df407c53e4fb52b86d39820673f8b42628bd85e1badbce5707f4542e8d9feaa75b4c68a9f5cda39483d865bc61e60da84c708c36ba3270e745e486760bad3edc4d66aa387882d4c3715f2d6200c6ba8790cdea6c009898d357f2f43ffbad7aac11bccb1a9cfc80921986cb763df9c0944e84fb9585102512675f4a201eed07998133b627d8f02420022389a08840634d225edea04b652b6c2a1b0f648ee25bd495819b740e40b7d59f39990582e66c60f1faa342e222ff0882898a85ba5ef8a254a211168742f98398ee7dd654e47515be1ed8a51387fa460333895e8859508e2d515fd0dd5dcc5e4f8d65ec01b0294ebcb566c988443442b5f4f79c42562e68cc0c11086e0d662601fecf0818bd60a6620d94aa76eb656c69e409da1ad87a5020d6f67f20885a6f70d8926d204abb330721c0fb0a61784aa2ff0d74eb41dad9905577e8d405cb7909c507e2d903851d41b828aa5752764513b20b212bece1754446f0490c81eb6a29719504400f8d7273d04590181b66c5df170f4a422feb9d89669dccaa2acad3a5222e37482308e003a3aacc85f41235549affd35066f14a4f7b3e4a9aa6224265bdb36b19bb54a054745d6cd161acc1bee1de265e240cba64ea6cf4c9f573bd6d4bee75881ceb156b6d415231f9c33363a23c5341f86dbad4148e948266588a0db51017e86549cf6d92c7eed3dfaf204eafec8cca82c63c8827d613d0b3e5e5be467b1cf8ff3f1bc8cf663eb741b06086a9dae3b848a5446fe531ae528cf89936cfa17ca1e1952212446934882119808a4de52f69821e4c31736c2026b433d5250909baa2d0893615314243ec8453223d17c0c67140690fd99aae2c8e30da08b547aa675dd1d04aefbefc0702eafacb39735f4271bded77c60c8bf00e00740ec30f561866572bb74b8aa7d2fc6b3e9b514d6e82c9bf53ddb8751f491670ae2af941958dba1e6e060cc3d923466365a862ccd539a4be39c901e921c4c673be5f6d42407e351a89a7def0a8385f9bea636f6cba090c60292f0b784dd508533ae8ee9b095c9f537c719c206fa44004c6d1b6bdf297466eb8b392b68ec5de8bbdd898611859977eec4cfd1f91e4fd0d7b10810279aca62cd133eb8f0fd052535e726e78a665a044f113e335f4dfeccbc90e818608732b07ff374546d23208ea5b1d3a96cb68dce06308fd6da3cc80a30cdc92369f5c7d45f1a8b8928c9770e0e2fc215be5df48fe8e2dfb48294c9d0bca764c1f301372b90d48654e2d01bbbd53d46a5b0aebaa2212526272bc922072c61f487ff3277eb5ea6c5c07761cb8a548863db5b094022dc9214c17bb92d64839ffd673c91e2bd3d359c0b52d94891a7341241d2164b5256654191184baac60637b431bc9ec8775410481788d3dd2d1e8ee10b6a5c596b4402a2a8712a9c482554f8f1e4422175a637d408e0dbfc52968607d6e1da971c5d878b3b9069a1b6c2e8320d51623ca6e5a8d68a78aa68a0ffc7a05fc7742e15aca718abda9578fddc39cea17a21348e01056cb3d06aff6cf5120129d969d113ea40b14b824c6fdce73c1711aeb644100b2a2c7a7ba5d3407bd192c397e06221b3f18f588bd53850757df31e176a29775fb2ec5b91fa01982cb4e0ee5fda3f9f5231985155956f154568c401dccf41345229252b9c4c9bf730e081417c2c7d040d6e2083da8ca0bc2476cab892c921347f5838cfff6814d83b6eac58a24ad1400dfdcd69306ba161dd5941b920a820c7acb782c9748849624409c954215ed5f8ff703cad9e15492c2228b575941fc3b0933c8303a310c080ba3ce09dd6bfc464de485713a12332e183ccf126999656da1cfc7607e8d823b29596f1a0c9c006c6f21cdd394066a0c83baff44d9bab20261fed3afbd454f809042234fc3a61931b0d8087a39267557542ff825bb9c300023d8dc4fbe17e80fd606dc11e705895296879acf943d555befbd0b0a222e2d16e5a646fd769fde3eef9072099e0c168108643bec6fd15a5715eadc19ba7279bc624c6cda7c749c7f3194f4dfda685980a148aa0f9110e385f8389d677cd2682df9a1ac4b2516a01153373d4fc9b10be359456b05cc70ff65985187f4492e26b8f352499372652e37a4fc48721ddd1a6fccea8966730535407cd1ba993fa8f1be57f6313b51d36307526d08d170af801605ba6d3e45de5075751f1ea3f559a5215530a22c54bab6debe4db7c32e47ccb5e3bbf090e7b72ed2de40616cddac4cceb3a30a14cf242d547db0952afaac5bc3b008cd50560f389d2cf8b5271adf2a5bebcf99a8ab40739b15f7b67b02098d8cb7f96fb598be7bafbaedc47f56d4aa37da21b2bec143f52c901986c07156d7604c448485cd3950ce1d23f53fa345a3e9b88ac9b3c02edacb564df3408e9c23659e70753af05732603a968bcadeb3e0b7715a1db34d6745fd755a36bf53603cf4c3af450468010fc610e461c43bd38f1cf50b06bea85bc2b42d1e861214282744008518b02ed9a15aad74126028c95406a5cbc5541df593511b328ceddb95536aa8277b090f7220ac8a97d309d1235fceaf074828860926b44941820f3845099d217d2671a6ba9f947b769372923380b807204a66113012b047f789bb741203b7683d7b7beb49d644f5f14f707120e453a08167a434cd506d5d6d24594b30865b3ca7cb90a75e82139e3780f6963862ba89111f42731c2ea789f7bf6ee3c698c3a3c2501107182b58a5ceec5b42f5f572a35e56ce0ded4547202578d85d81ceec688df6a71603b3561ebf53cfb1562c778e6d6ac5f7280bb5004c0c217eb84183db3d9753814b05501d28dbcdcfea1cb369cdbb9628d1fd36987982874da9ddf139a833d8375b6a574346f8ef6dad1de3adacb477b7fe4ef47e7ede8bd1df5b7a37f7bf4378ef6d6915ec7d166f283fb39c911bf380346c6b9d196bf0f794160989e51f68a5ef5ccca2d13c1dfa78e3575f05c49369f6fbc65b099e20ae54b0b2b9c3d1637c9eedc7facedcd959fad551609c703eff9711d4768b3e61b36ee03720130496c5c17f3ccbfd769023867a1119bf8144ed659cbe51c2607f0e385bd3f54b0ea2c37c42d4610427508180b2e1155d9c96212c61927ff4406ebdb58f8d7b7fd517312e1af357f8ce3402addb45a0051328e1a000c7a9b42c7baa2251a4cf8551ecb0f093b02daa33afb9893a2fedc4d7871550156941cd4efad5b69aa4e6b3be103ca3041cb14ea8a0ac2226c14e47a07f63f1819557848363dd0ae1fe81897ff8df5a8fee4b2e14285198a1a3fbd76275fa3833738e04e6961584632541572f8eefbab72f802745b819d01b074eceb70c028388db1178a1c8ead31b40dc33d1ba3632b427d8f6f9f739c688438a9a9a52b11eed3311d48abf879fc051f898540e022fdd27a123d2c7c2cc157f4cdaf290874ec3c647feef78c785cf5edd4a4d4a69b8fbd2b32f320164d998467600bfba4ba8b02ea4f940eb95ba2d99c7118dd15c432c7e93ced03981be683108c6dcaabf629c6f46018f837800f8781555799637cf6932665dff143817d027338fabb5f9ba9c3017cef2fdf951a8492e90569513c1a8bc7ded9e92ceda6a269df89d57b4eecde7762f79e1bdb3d0ec7c67cb8a15c4e32e356c3732d627640bad17d8419ae37abfca924cb48eac6016ef2920046dfbc15003f69bce03030698561c7d773d5493d59931e3f248e39d40e8f48e517ca8375da1c1d5c999821b8ead6896dfccceeb5166ad2d0e8a82e163330c1c6e40e97033fbe807251cb609aed760f8814c75da99d9109983463bc7141eccddf2394cdb6dbd778417526ecee53658d3a21bf69d1794449cdcd90c6c3286ec1670100819d961d18f13181056142d2773932dcbf54e8e1d6ce74e230d221f8bed109d663e6614735a375e2d52fdb6a6864025c8b09ecbca8bd6124f3754263c5a77b515d8890822df102bb755a2eaff5e4df2d7a1768d055d1d751e15da0ce30e90677df266deb09606ae4d548373e4e09a340ae887841301893bacdc2cadc1305c65012751de87c6633eb05479c07182da5ec38ce7ef786ecb3ef9c3b8b660d53405b508cbb990f098892412362f45b0ba13ea9712bea21577c64794d4552f3da9912cb48324d5d2e497404d740b3a8c109c5bd6ef77441754e5a581317bd12856616a1b9945e7e0c58dbc1d3be59add9d08ca603e2f934965131ea216c2e1aeed461ac13669fd24d03af9c609011157ae1f2bf106211d53c7cee2ed07d7a94f9f019a3644335c22849eb0300b653de609d542ea91aab567842756ba58f574c62ef757722ad37132eb62eca3f8345d2159345f57fc40b2c5f99f45bc26d5277f4679eb90cc6f13c2818dc76adceaa811e90f04c7574a1547d05454880cc272a9a1130f75450a688206cff36784687009bf0a318f597b8dd90e5c4228a44a43e66d95a9dca10e0beef3d1773820f82ce5ea3a8f8ebc886235d1b2a4e2aa343779530acfc2d76a833597b7012f439e73ae7e8c3a3e7c98f6d5bfdff3834439cabc68da08be2a67672920bef3743132a551b96b4e4d556cfe3dab453abc33e429d7aee9d43e8a5b4fcc585d2be174d1a72c883ac6bf1f95807633e88f23bd70c1eee9b3aea9e123090fd6a75247e1f4975b847a07b90d65bc78ca2afb8faab6a4f4c4105b41a7b71911a6eabcac24abde3eab91fa4c0ed44fc6c0050354da8f18016afb22e15e2a2c2586023a0042ba8cae566466dffea30da8cf56d5754ca71e1a18ec743d01341949e80ba484dd68aa1a964657993066448552a718851fc7efe6db54f31d548d50cd241ef2b8438a057a9caa58da43e26ca105a5a43a4b9f113c3d909c6f4be81bd0aa71d64a34ef9dd3a633d425706fbc5045b4e6db5ddb8b16dd6e96598383b47cddf93ff1cb53f9b94c01d04b5648dab1d6e0e3fcb26edf7c7118f34ec6b76ab1d420edfe56cee314fff5ff8f02e8c0462483c222061e669c085c53b5f33d5a0409c93298bab908610c747e2098f1c18be4638442821351a7fb0508abb8c9c437a42ec97117d924ea33fb97f523338c5b91944c42b12daffff5788436e09123a4c0a82f7dcd80953ff8763574c85655c3ac6a0e6ec55c1485773d88742ad70bec0a9d66bc0c92bdfd3162d68a9d68bf185fb8981b86e8b2cde8e7a7847f755a5c59717b0b6da8505213b1c2cc5a8dde1326e3e66127d80ea34b83a9af8bb65a4277be6c88921b59fb07b36d8f57c5c0cf73749588b9800bd95012cd7fb2a14d51f7cec396253527219910142818f95cead1d0492eb773adb9f65d9643c00abdfdf9f0c7a82a864aaedad99d5c1120d431f14c29bf59488a8690836808e0116ffd50d920d0fe9c8d7308ad42f58c5f83dc65fd05ec3e1052d6850a5175e46c5378709d2233a4063edfd13ee0a61e4e75f620c6f91abb7e04434038abd838a9327dca7171b9ae7908d82bdafa145584a507b38029cd6bc0ab7ffc3f1ffa27026b3fc6a688aa57a6e816b4ef727288873617eeaac2dacb1655014a10a29bea9e828b569eca6033f29efec26fd400539f50ae020151008caaf0360fc2bbac755cf7a62ad250cefc86dd009f33272d69980179da5a9bf74f37e2909986daaffe52cd1d1c40309d8867bf0784f1345e5058bdb82dece59bc071a899060d935420b6150161b9bdb8a0e547ff971a6cdd5c69a7f847e865d2fd25e247c74132b13b8b8e8d18a281a5c555e1f24194d45e437ee11d2ebb83ffa28bf774c9ccdecfe4780d02ee29df679cb5cfefe6b339c184c8a34243f02c32893fe45c855bb1de1d23daff40a15b071e090ce0879f82607a64ec74338693dfadee9d21ad02613441a7d7c73962a6a37034d3952c0faba35415e05161791f4296b9f94dfd12650e973c2059ff7269d3d7a54ca3a9808e3e50fb31ffe2031f90d1e84137df8838b61a97b80c8ce2ba811884693d404f6fb354df7d065124c34e74220ead75846ad9ccfb2220e062ec96debe019f66fd45f045213025bddddc6e4a8e95f9c92f7e469805fd3890cedbed47a58bf6eaeaa0ff1a8fc7fe506856fc6085597eee9fb021534c8e88ec754e1c3904d9280272c12d8647018d4a30c24f0c759c3865c54c3d7c412e9f6aa2aa3b3a1f3798294e0c7f82c2730222d2822401eb8fe493d42349464002feb685a2e2b15c0e1f1fbb253d6874453bf30efba91d6bf7b92d3e79247d8c6ee60de38cccd212ab2e546929eb346314649231f1f642a493f159f0e7c225851403b26cf3a4e8432aa2bcb56a6f69b620717daf846df638aedf99144af60b42e4f31256ad0b448069d76e65dd11d20e67a90ddfc0124e8125c48a564867f7070f020b6246fe18a46b88c04288dc4b021cd2d44bd920981139d88108ff622958916a8f0defff5c3db9418e9734c0ed595b58d539d92743d3c4a6a3571069611634576b93476fcb1b53e7676d9c00a965b38c98d6eef346458f1ddb5a83df4c8c962c1f6d10ae29f1c0b5cf43c1b7fc4241c4a9b5a350cce64ea39cd4dcbf72d13643995b1ea9666982545d256e652fdd2b8c6deae894347c6df3709f07231a6a9ba5e8ed866002b70f08fcbb32e9e32b7df694d8d549e58e03fa4254c48d45f712f9e4126e0d03d6725e7a13e91a7edda08d0f9087dad84b3448a0af8fa031275aaff5d3c3be26fc39bca36ba3ecb2120fe1d986b7302c5a5c7e2ddbd83688034b1865494438d9f84468283966bdae272ed0636886b426a6e790d3656e7cacb39356c68fa1e1555a30a64d5b0698022c8826a33a43c44a383bb4a6a2e3a0b15ef69023e6ecfb3c971e4e8afc2fa47f14f2658ca0fbf69a452c4cf6cebdd39e3cb375b0b0c402064eddb604c8e6e376f4dae5cd1acf2000574ac73125760deca46e5d853b2353ed683c73af6a7a0c341a19d810786427ef3ce1db38236244c36a99347676cd2a28298dd00d2626c14925165a0045da072e54a66edc3544ad628c110b4382616f9ad8d87b3969b4bd3f849ac743734d0834aedf55dc5ee21d98978cba2b1d549ef47e262aedcf0c0ccab7b66dddabe715527894c76faa758874567a9713a88568efbbb5075d0da8c455a3aa77546329212652c22f1e7af6e1cb220e790e5b036846f6e61d011105c008e91838335bb78201284ecf10a15482b01f0f094b8165530817a234a8f8e44e440d29af190f5eb2ecf2f2571c822f7863ccf0bf4322e6f5a0c67ecac91585d159dff0bdc484c0e43da9cac02185c9ffb0598b3fa5a65b9ae88dc5db18c199fb26ae203db82c0c243751de9bf475f1ff64917b9520256d2eaa54fdcc4bda09c95c72f32fdd00685b22050911c117222957847165bb3ab52647534a3165e701d7bca9e141f0c17775729c1b228873a2ca451cd06eebcb26683e64152cefac64679f1a0cca9b220274913877d64347ac213cc594b6549aa0802be96cba937d9537a18e6894bb7e862e09cd552cf841e65b3140296052b21d10aaf03b6664a0004e08839ba5c5c9acf036841fbbd633236d801ababa4c3b82b4eea847251bb7baa76c899955c4ae8ce47b3ac110bb068865ee550931691331a2e660c6a4829c49b45f4d0da59b3d8dea8cf3996626385d5d2518a9c6ff6c9d1bab8ddb02bfe9b75aed7b8bf41374a49d118002b549d3a4dae071ab616e15038381e28e5894e6d561405275243ca2865db209dba3ee0ac51f4a4c538aaf537b58d78372424144e82790ed73cc1b8e418a6bda42ef7c0193d9605f69d62fe1806451f8bd2dfcd11dc98bc6663e737a6d8df03a7114726ab401b3832e709dc64f09df0244f980e4c99e4e5ca26064e8103fc5366836dbd84ce94b0e85866d1cb96e8d3fc792f835e432f461cc91319625445c77a653c9f16b2eb74e683f42a5b119775c9a971b06b2a0454dc40eb524b50fd3f976a652b93fbcc0cdbeb4657978e0a56a7ab366b925f81f73eb8db46235cd495dc795f38252921f592ed95920f191e4e0d0db1c81450fe188d82024886327084243d408c126c641300ad88f36c6e0eb8b3b8f6abc8e11673a0a76f1139543c6e1ccb650fc352a8e1cdbd8dc0e00b7b3ef7f8cc67e87f0ec0789cd66646c4adf4277f7461be6e58a1b754e52a65410a259fca19c3698fe86eb54d84596515cd2c55259d31d6089017f544d57cb19418d0d9e3827078d26b3ede484336fd9468386acb6bd40b7cf27a97c2ef38f2ab2d5689e24eb2bc15df3fedca31ad9eb55be0732a5142c79483b7b4c940f6bc82e0d57312656eb9ac0b48196e6e24421a699d35ea7c8fb65c8d84aeae35daad92701ad99926434cbe1ac90ccdb80d2838583bf11b43ac26e610214e4b09f63de4ab46a2e1030e67c55671393f6dfeb1ad0263cf8288e7c86cdd7f01aad5697650c4ed76e7b091fa688b19f9782b1caffae3746d3aa623ebd768203ea8b008f200ae7bb65a2a344f0031dbf8c15d94dc25b2fb13f33965fd8f9455b3df4ba18aa1989a2955b38c0d5a6f4975b9e10f5459ae3ccbbf70e7e6e7aa9b3c171f2de063c3b35966229ce60aacd2ee1a8e4010e20238e0b0bb346826812efff3b857d723b13c48f75b77b01bea2ab54966f46f88317204d2afb99ccb4eb7cb302ca1d72f4e9107d0108017fa9d7f2ad976e5adefab36a6c250fe78cd24eceb323fecd06a40aeee80988048de12d9d85e0908bd9daa2403f92e7d1aed8809039842b2f70b4dfbe1b9097b7ca3e5e50e41c5d0184c504f70e20bad0799d136efc9d45760346797508c058a612410c33e8fd1215fef3a83475ffc7fd957ef6396efc4ac0e44cbc5df301ec81453c8f5fb00a80daa060df0cf71a56800bf00e77809473c40977a397901fd983488d425125130d1238b2c8cbeac99b81d308280230d11c758f920a2e6ce51c99f97beaa05161f04b2f1ddf325170369e3df3ad8921fa7229eef95068dea0705ae55d2dcf4f1c830bedc4eed2f2b65aa8dbed45c1574a364b04494f725003705999e2bb12b843705aef947ffff07f1ff7af2b40d05dd975e161e7af4fd936fedb2fb9261f97ad993ac5036c3d0376638c50f1ac4b5247e265810448206712a7093d1b4e1ac5bcf5b6f630509a80175c791de7f28334441477fd0910332e25d81337c8d1441b2365e69e3cd90f28f23adb853eca704ed38be76d2432813e5e4910d5ba28d4ba086e052d56b1d0e8eb43f88e89752eb1ecf2b8a0d0d54b6f41cba4045e3b962cc0ac30f7fa3a8b465d7b585f10e12d3a35cc9b49874d7f78a39f78a163027b322be33902cb4a4223e33242b810a9bcb5e1d889ec3e62b409533b88515a6b5ef4d4fc50320772a96f8537c57d4398a6fb7b79932fba7f4c78a6eacb07b6664e35979e899c2f74666478887ac7c74f83ba2d840890c76b3416b67ef1d6c50aa50faf8a558e88454a0770be0ba4351754e0dc3c16630539a60d059e88a134a40b06b049d4aba8872a6bcaee454e9a29f802adcf4b5e358513f7d9c112ad43c4ea1c99b7406390940c991f0a203e7ae752976302f7c3c6997653ccaab549e1e5a085aaf6139018b474b0037111f0213de6a30d41eda26b89c80700b29f0aa7ff6745c9a9fb8a260b465459a0794e77dc21c8aba5a89bddd9aaed1f0fe9966d6bd2b2d6d3a07147420c435eb7570d9847e3aeba5ee71e6aa604392038a2ae9db30088df9550220c225f29500502ab5cb40e9b10b9959dce667f129a101d745f450b7c9d0bba86eed80c2214c158765b3fd013db4e3ec1796e04164632529fa3092605e4f4fea06e6b9c6c51dc43341841b69a832bab16ed725abc785e337a34d04687a49cb56844b098202e5d6131c41222d0409294afa5258c59045b809e83fa5d956df94c8424cc2338df8ee0763dd19061d296e928ed08e162890fa2d3757a842f5c41829dbd4211888b5103528b3b0b808b1608354fab3f60096ecde52ed077d67a0c3f12160c0d88b3e459ba7594583111ac4b3fab002fd26877461489d516c3b086f9b8ec89fddf6df71fe5c0724214ed8b93f7cf10f8373917401b67d0caf49793fa0ad66223280b321151a1b033f5490320fffa01e14bc351544d099641ca6d29bc03d994b8a6cb1b928d9b870f5f9d42c91305009dfe034074416927f7fcb4c6d73d6fbdcd2ad24fdc4e45d3ceae7f832a185bda004f56a53824b6293f2cf394122a3dfffc15e441eec8bda07647ba3aebba6522202d49f85697f9c8b25b91fd3b26309e7f1b2afb4d4d38b6414f8b81d87f4a712e2e43087591fc206e71ac76401cf6e4f0cae824c30ed51e71501c20ada6532638bff576cb1ef41cd8435f8ee570a2e369766b7c45f3f82fe09d333dc26705b681f0cd1c7630200e441c76e091d74ceb1fe549107a80eee768c8e672675be09cf42d568a437d1f1a455435cf5d13e02a0fbf8cdd7e465805e01bb7c43b33d7aae02c308ca02f7f7d2e0b90535b16f97af7344f5b06b4a9232035a118cf092f35f121a81dd71bcc445359661df69ef91ccf0e57f107bef3ccefe7e9f5e2947d82cdd4711ff8897470f7b28b18810f0dd85f5a8ec7ab959b1590e2cdbf5af1b733594613bcfb6834dc9b523e0577f6dd25463e0f9837e712c1438cc6f4145cd0bfe0fad33f0f53eb67f53c9527f1fc30191d0b9dc7ed5561c23378ef3a635c9d3c3b19c20d423aa1069b7761ec47a109c74181ab8560eb1b0a93377e3ea69910eef2f0345071ab20d00c1c9be9cb2c98ae792e7d7366081050b6d727dc0a96c0de02e4cad3de7e55b3d51b48bc1fa97fe0bef4fa6992ac422590eaa4e03d5b80231a24d027b0de2c8567f991f0581069a386753f8fc0128ee3edf3c7f80ff4c48a443b8c45a7cb7b171f116051e233b0b92b59fa614a9b9844a8230f8fff0a81b7075cb2b0c5054ac7bd24f8afacba33bb99d26531ecfea0bdc829c0be04f26e1854518d1eebe7046a0dce1fbebf5870813aa2d876d0a22c5c57528a07448597f8da6240d0fba56df46a28dd03d529c5368eb83108ad5abbc6ad15a74ab3946d38eb6d5d77ee97158f91671d45f213f8ffae13a0bf0265d2120696be36fb6af490e960bc00cb073fa9d7d97afb7d7ea31c100dc061339d0872ddd5cd1e927b08c4a9dd588161d355320c3f04b561e62f3b0314df74f2fb7d627fe1ebb2d72eb4705fc35cbfff629746eecb73f87eeac38b0d505a8ff74c35f67ecf6d31cf5524e7b49bc66dc38555b0723541d661e8f570be84bbcb67070f3e6da6b16abdba219e4560ed3234fede26e360410a2faffdc7c0e50e05c07c00ae6030dc5f98a2d21940335be52038c9026b71fe06ccfe3a9691107efd1d2f86ab2d3759d5ad08e560f2406647881282b6c82d2996a81e8bf309ba31f77d613b2cd0c7c28fba40046947ea05bd31cfc317d4e9d7283211e56426e2e4ba30c82c73d934bbd3653c15fd07b6d79ecca906e439315999a3d10fbe6e986dd778950de56d0d666ee57765835db6e9f4f8ae3de319ab516828af1fe2debc5e3bdbb516ee875ddf96d2de5d6188c4e4070c7c4ac061f30caad7f90e83f66ad6816593d9aedb9457c6d701b317d745cd6e61cc6e8d6110369a99a282d8c9a118be539e448930e1b4f6ad46e1e07d6444f418b499b8538c5f0779031f6e7c5b67d9c9c0c3586206e29464afe730be328dff84b6406a0b8fe51b2efccb24d38c4e227feb362cb9baf1ae8684c06b7ab306718101c05cd02a084f083016f89ab289514e6c1c3dbe450be0ee266710f7a8eae3f502a048774d714111dfafe5153254fc38df3ef4b30d5e9498f5abb6e069f8608372d01074606f3650c8428fb6f37c0869ae9f16be221011f2614f5c6aa96ec69322ccb29a46ecd6aed4f0cca3526961dcd45a5618475fb1eb5d0f6d7663c388e9de672b48f6791d5b9805c8fcc6489edad4c072c380c50fa24721dc80976aad6f4d960017be27e4595f2a88e12d68e0a9495973be8d4884dddc83c164722c1b7cf3eac55aa5df960565029885083aa16533bb315e330619904cd0d5e31103f74b29d215908ec56a0f1c1ff839e97dc915bb37e1389ce98e66f0d6e20900ef3fbed98472e0706a9914be4134ae1ff082cd02b0ce622d56058cb2c511e248e8052a98e3e185d183cf2635cd438e0563990a9e282aa24bd55a5a5c517a6c03998541ef603065e37aa81f766b1e6c6f3e3ea1afe79cb50e7a8826d9998bde6c48c378412475834513067a81ee38ef4a62501abf78980cf2795d3ff481d16752349de56305430a8d02b20da8d5070ceefb560dcbd86924cf25ff476b60e8158a1c75c181c0da2db46fb09c20b30f87276af684275c84aa6ee4dd6344ad5c32d4a7def13140e55fdb3c19212dd42b99e606b334187c460e3ee4311603466b7243b16c2402af100e08c6e163dbf434a2fc69d7d0980ca20cefa24f228f75330e24f3853c7399e03d0cfbf8df4d4199f248f2ab048df7a45a4ed499c7b7e0241afd778adc06fd803f14f5220dcf5bae332bcf84ae8520e3a19146cf4c0dadc96745d3e835ad9f131dc245fdf0ba904dcd1be186ea31f41407abb3eb18a35be542aa64e353150d6e1b2a0158897570f799e78e992c2f33096e2926fc8e83a9ff5434c3d7b06acb3fc833156f927086e90dde933c08ac9ca853c844b3ce8703b63008a3b456cd17cadc4689fc29c238d802790d03eb75e6fb42f7e0a80e0c696a6fc466973b783de552667c123c24cbb8481d0ffb4219da0a2fc05b5b1c32fb8d3f04e18a66b71d6dc582a153beee09056dd880256652307f39212990a23b14198d550491def7491cc4170035ea91dd71696c127ff4af2cc45bfaf6cfda8581c464d5102b06234926a921cc00066c1989e232b89aa8d86405c1d247345fc7e492585dd63f5c7c593eccc2389da17117f9111fcc9c0307fa19bbf0d33acdda46c39b2b3cd8ded86be62238028cc77205c7cdf218bc914bc82af2f498d1a6ef28214870a8d0c8d3fc49b2d367ca7420599de16f8b1da7226070110346e90894f749e551a43b116a304acf0fac753e395a2ba3f6305c78621a8561ac9177fac9d42ea3af7f3c9773e3852ebfaa67156b03728238368f78612bc29ff9802b12e75a549c9f196ecd6cb4c949661cdf10ffd8141d46071c24df9b2b689fd9bb454ee1729c34e16fa4be9fba495a220f7247b2e993020fa1fe6715f975f1be74be81b5f9c4fbad1b21797e1c4fc1eee00d78ad31107c1452054b627cfe0cb630c88e8771fc0838fe775113d66572c0b3969d579c588e754a6f2501ac913e94a28e67fef552b00411be85dfc6c93937b322b7da8f3520c5afce745cf104235c0b3139074958884446084aa36f57f78fb0e55f1870d345bfcb580351eae9ade968dfe14a5e840c40935562ac044706bafb3686d4dc43c4f21f3d4f87b52ace9f29248d32b30ccbe5a1e5a69d326543efd93a4bfa173ecf171a6dfd8bd37e367dcfd06937484cfbc99bbfa1679e11a2af85a7a0e05722c36a4e7dce42b29c578bba15f858e0018899668487df550b58d7d7e9d7bfb844b565b986291e8baa2000728e25b8d77aa1f3b46d0a1fc013815005900f7dfccf48ce2edbaf0ffd0cb95a6da061cd6b4f5d59a3e42cf850464faeb120f4ca86fc4c48a8095d3b5f7081c91c39c36073508f4256bf942bbebe4c732bfb4d8dc89c84a1281eddd6310befcd0b223018ccd424c09f2365998b01edacfe0baff02830f0e95a803e1e3e2c786d90497115572440734c33a26df1842bd6ab152f96a6d6490c7e373fa3404fb67dc571f5c34478fd01c5ef72df829c8abb8e6d3829911bb5b3e4009da2729d3ffaf4d0b74821a9d807ef5b7b7bddfa16ca2fddcd4cb777f967b5f6ed942a8c7251d8dc1eb6047aee0a12355de90525af27c5a60ee61a0cdf2852dd673ad1e67d171906b2051bdb05ca5cfbf8c80183d76edb85ad67b12be80e81b2cb1d84ea59ab52a853e43b2878ce441ecfa5cf41c63c9db189effd11133e09d41c14c6095f013a0d96ba11c62cf30254808929d59ae321564b0009c6821080c25cc6dce23e859aef2c18c6ab67daf3504a8929b083e254710a730b2954eccd97b09c4e3e021a793065904b4cd4c7ab33a991dfbb91308c203af58bf5049f1d51832fe8853694f26592cda7c069ec498ff6420e6be7ba608afc711fef92896ddfee1134d30cea4f31dccb7b78f1db141c0115923756affe1b1806a5ed8f492eb9ff6aca9c3c22903b7f1ba55e9c870d3ace34a990e21902dcc5e8a2462f78a5fb31e020df0a3a53bf194a77bdd791ea1abd519e81d9cf41d2b27d2e6b17236ec21081c31efb47d587d6f7b9edb168b7e33d1ff73efd2279ff3942ccce2748e5e5be9753863b631e5549ead800ff7b4c9b021054b3959cbac0240a344af6786264ca7afa07e3c80c811941484030c6b5bc02ce6a69d2547c33691dc08c561b7ee10a74683d7e2715b505bd2e8b3f7a09abd68979df6aa8db1feb159050d1cc56385cee3a150d883566ee9c7c606f6a41488ed6fc8eb71aa8bf61d85a28c12f5a725e8d6792609b0fbc6a87db2ebdfb0475bd17f1ba0deb4ad93924a021cb8040b43a424a2e4c03fd1bf7e7da9042e4720d0db7f9877699d055676ef4d04e9725c10c50788c3299e385cb9f3836ee4e0035a5dd29273e0033d450062dea46097243fca637edaf79fdffa35bf4b1fcf479b845b4e305a194b29e19fb2261c92cf0cae5108fe232f920f825123245bf3960b3d59a6bb3768402a77920e2160d16bbca4c37689da4892c896490d07391e7062dfec6da92bf93ba943cee55cbb2bd78ed5f7c6eefc7168540997741ef842f67f0f65fb0f3ec50f0042d5fce836fe7bc1eba33431606e721e1b1587b863649241148089ef9785466567f44412cff7e20dae7f8c282bfb34378aa005b80660fc23758654ae59f037f2dce2aef74b5d004b40d35797626c5c602f5cbb57e26d0fb443acd8b241f86f311dce9eb69a556552be86c0ae0ab52f34d143d6d60e557308cd19af0266145ff7d540a71cc4f4781bca83dd695a267fe74ce445b03e3b9f07de5c4cb14bf4d2f39cc73309ccf2612d36f81a4001be5871c6c4d51a5bd07c314637a6089cffb3ee4693cd4370a4313e01b753116eb06fc26dbcd6a011c96204b685a32b189ddcd7025ace6a0824a3784a5989044f604e4eb8fbedf99c8d56b49dc6046cf21008a2c8ed531ab5121f7bfc0f6b29283e0eb4fc16e724af6be3d2c8c830f97582cce2c90ff78fa402347c48c40623f8d86fcadc7bdf9667ba9f3b5c30add10007825b89d130ad4210d1c436dc27e3d0247bbf9848ca8d8fc5250551fe3a66386ca69273811cd921c43654c191d1eb3c6733152fc9e9f05d3fa4ea2410d7574b27a6027003d41e9c1346da8728f95e7b5d25559981ef374310a2b89ed19f718c6a534bbf02c7a20804d5ae7c67b66bbbcb114b0a5a3ef3c7341733601580012d04c293ba624d8ee22fec83b1de0d7367980cc5b69e80fea040087d6517249b68320b4520afc4c4c70d003fdc67d40763f83ca759bd8e22b6f1ffba10068b529eb951bfadbffea96e17ebcba63cdc821c6f867a4ed4d21edcc06ad713af0654d5a18a6a9f3110b8705e5d897b6d30ab46046da4429427d913603344d43487a6a46235b6beae00b19d33377a0ec66ee17659fa5ff59601dbe59e52434eca3baab183a10c6074fd05c79a173251e1591e199b8a8769d131e2b7846fcdc38fe45a6115708bd6487d0080f190f9a06553f6cc9240445cd22e2b89059aae76524be09115643ede30a5892d398d99bad9898619b97f2f027e08cfe7336fffd4ecd116cdca01720288521296516101caa18b007bf1079fbb019210f64f78100b366edc6f4767d381a6567e2c9a6b71bc6ec1198dbda8c6e7a926e668a3790281f479ca88aaf3014babe629a18f0a3a6b1ba09b2a840c0a858c78d4b006d9842b2bcb4d06f13c0f4a06ef7e72ae2682747a3e3ef3e7466ea81e82c053c690570e9d911d9db2f0af51d83542650a47c2c0f4bc5037512ee3cfaa78255f95026a1571dd714087a8884183cda6951e7c1ea019bb19c8d5bd5b92faf3810100a5b9a72953a88069d28d447fc3ada2066028f5225117cd73bbb415575b0acf0f07374da09f26da6e02a4f004be2f0563105d301656493a7ddd83ca709f70d83b58300fbfb2374322f7603394ae667c0bb2d96c4399747f0874bf26991ea26926107df3d9c0e01e8fcee6ef01eb1b15c3b17e6108b02fb558c1ccc45e441ddb5247dbdab26d2384904608217bcbbd03f110a610e70faa4ae454be304a347788308281c4483a4f749eacc408edc00004d408065258416184008506a6d8905e2f0001257a419324ed9a4cbaec25831310c9400b283a00bc7a926022060daa6002084309298149018329744ef079461950931a64910935098a4227049e8b116604450ca48042083a3b3b61349941077486e8b00d0e1e347985d8b99a73229f340a7fe83c62235f9d635226557bf61c93a81115525c815d72bccbec77e78e101d56d7de3db3da316bd38d81241462ef264fbb569e65683ceba8f16cc39fa3907d8e53dce73884c2738462e33912a5f01ca3a8f01c8b56788e52c0e768d47a8e5358788e472d3c472a2e3c47a41bcfb1ca0bcf3109c7732443e659be60789639313c4b1d199ea5919767b9737a964750cf92e77b964806f02c7b04f02c9d08c0b3f4b1e15926a9e15902d1f02c9500e05906e978964b669ea590eb594e11439f25144c2511ccb38c8265517dae333cab589ecffad63334a737039146d8f4b963b293078b6afa913b79606ce6f08b6677583d9b4a72583deb62b3985487f9a462b2a90659aabba3b1cad4ae8a9494338d5430a6cea75db99170129a151a356e2f0a3652506105b0c5420b2edc7801870c0c314479b1b4e864a91494a54603b0f4480096520980a54836585aa5064b9368b0940c0058eca5c362393316d37159cc08b683553b8bec3c62d9af89a87c599b06671369705eeb2a8dd42eed4ed3bf4fd3f3f7d17fff6650bbbe9b8f613e55cf9bf75cf1e7f2acc2df639cf96e8679f70ec6cea00964a7920627edb463edabe93ae9d10454222f1b99d3ae9609547a76ef314a24b0a7ba9ecd1b6eb1b9a3e0f9926d223c37fcd90d6336e62006490885f143c0eab272a0fffedddc985e56f7985dd6b73367b6707ef2fca096014577c9f1cffad0e07c661d50463dce93c8a874731a68491176a1944a209d21708eab695a2687be58f50c813145cc8886c080a20d85018496d19aef8689e994062757733a9fced101758e2c6aee7c3aa029189276650e7f9fa745edfa3e3f89e64ce9f33369cecc70193e4f73da15c3e7a94ebb60b84be6f374a75d383e4f8fb4eb85cf539e76ddf83c45d22e173e4f7bdad5c2e7a913ed62e1f3d4a75dadcfd324ed023f4f81dab5c2e7a99276a9f0791ad4ae143e4f97b4cbc6e7a950bb50f83c9da25df7f374a85df6f3144abbfe794ad4ae1a9fa751da45e3f3544abb667c9e1ab52be6f3944abbbccfd32aed5a7d9e26b50be6f3948c76a93e8fbddaf5f2792ca75d2e9fc774dad5f279cc48bb529fc776da85fa3c76a45da7cf633c58cf2c9a332b9faccff9e769548fb3929d33d82983a5af06e763b034a7c179182cd5b1d44883f3382cdd79c1d21b96f23438ef82a5481a9c6fc1d21e162c75a2c1f996a5a0a52b58aa82a529586ac3d2250dcea360a95083f3d7d2291a9cb7f3b7144a0d4b891a9ca76169144b8b1a9c9f61a99406e7632c35b2f4a8c1f9153b8b666b9e65e7d16ccd7b54f0bc0909cfafaae07998243cafa264e0f997179e77c9c1f32d2923781e851dc1f32c36ce56b571b66e689c5d3ae513a212b58b769aadd8e9947635769f3b1f29b4640531ccb24fd3615445289b598f1433080286d4048a1fd0ce47d6d078fed3bcd74beac81ae88d30b55f10354f2222296a402489b2ebbd92f0bc97d3ae0f03c2803c80bd9ac8a0c951a540555e465548b083930a444b9af0032744e0d94a4446af9e1e2214210bed86101055f40821f56048d35e63148128091ba0018719210991048889105240b1adec108105111322849084a301447b982421099e11132a3c4580e084d445134043d082031bd6d3462f287a8a4004243493d07c3119224a276404308a08a2f411012541098794042b72984fd0a8a64d22a12a46aa1ea1242471692126ba9d25b400679a6384e7b58c1269974dbb26021afbb46bbe4bd2ae0ccf7335e7e77b17ab96a4c12cfbee046a700665cf6e07d4e0fc0ff4cea006e7a712cd7e4054211403cd19d4ae388de61111913913adf8229439787ec5c6b08bf57bfc6a3ecc524062fa8eda9a531635c3dfa393a427e0f8f5108d849840b4e20bdc7d1acd4cdf59a6bba3b1e9de27d19c51e8ab5d46a614202a78ce8984e74cc293e6e069f23ea076e5269a4a34ccde1feddddc31799fa63b771a9c5fc49f95b8db3cf97d1a9006e7bd3b8f44e068029d1d22843a77e691ce27b35d920667e7c3dd9fdc11b52bc7a428edbad4a13d5a602294cecf27d4634a29501520d042f64cd1833322ecf4a55abadbfdd13e8da6168d9abc006735fb249a7756ece64423229230bd44de4e772371543712a7743371e8cdc4f1e4949f54f883790d76132a769a89014901e96abbba55aad90292c29509b5bd06652fa162cf2a2c376a29c62ceda49a372029bc61191bd4a008274d5082c41332c828e1d864085cb0707cc244074fa400226a008a120c010826469630451361b685099e5071040f645a0b169045131d8431440ba2c8011092ac80a2a16af0648c249d952550948002274a884190932947c84a2fa051c40ea8e0c08a2182b0841f24c1044958010be8ab09103e4082888aa31093c20429638ca1841b43064ec660e2648c24b8c3d1c918232891a0eb91f2d5b8c33c2444d103309010822fb8c07d9c7d37644818628a1070f6640361708184107c61847b5a8ba9cd52e886cc051d70d205eecb6f479602239a74b12343e28a264806c89e6c200c23dc110a067ca28d8e0beca3338182b86729b4ed64c91381d9c7616ecff2b53dc72495518e459b4cd691635f0ed10dff4865843bcb22dc5c88c0e24ea8bbf94688bb59f6dc18bd5ed108a787623408a881e97dc0f3c7f352891446175db56d342865624bbed22cd3ad4e4f2af688b3f92c737a52593ad4c07decfed07feecbcae198fe985e79c4021f24810193288e8014e6be20b59179b101200c01471bb2afe89e946adf411f640018b6433ec800a8aca28b36b2ecc1339bbe72fa2e9ade496f759aa20ec1b0297bf73c04c32befaefc76ac74a69bec26830ce0d1d44325161c63119e71c57add45cf64bb7b76e527964a136772cd1b36bdf2100c9bda74ec9d690895bedfc9584d97afadd6db55ee2b37ab7c98332ea7395d63a9a9e7da72d4b32ad5e272636cad3c7b8b5d79caae1c65574c261b1bfc4e9fddb0f2cef469fae96695e92c3757d3eb5db9f9d8b4a3bbc964bdd34c8fb339dbab74f3b6dd5cb59b55d9cd0765f0d4d154a3db0e4a9125c2ccd42a5fa7566f57737eb69a6ab0b32c3f3755832d530db6a7dadedb263f1d269e4fcd9952cd3be7b76f87b7451b7d2371e89c499853524a3bcee4608f3ffdec87ecf4a4f623a60f699f76372893e86490590619fd92f146dfe0feeb85b52b23885d00f7a5662dd039d0ec43363c31761971609dc3c49f051a671f02e66c394ddae3b763e2ecce5b0322b0c1bc3a39d1b46ddb5438c3664bd37cd4e388d929f3b6cd2bd3603f01e00c36b48e2970e330b19a13856690572d81039c8f7bf6acb10a268030dd59e9d4ccf6d8d971e8eeeeeeeeee0cd314a0b7779bfdd1b4977ed09e692fddd393aa3de219c369259e5756edd98743c45a0edaf5ae0d0df6b30e1deda2efdbd0ae76a1c19ee0e7555d7e51e54e36e90cba468f5a9a71aed22a112ad63182f4cad376655eacf259f6d5dc14a6b5afc2de1f0e11637748e30cc72fbb2c1d2cd098de79bd06372154f9bc35952edae8e89c73ce39e794826786511b9d04bf1ab0a7d4acc25315d32eafc119e5dd1a9c11698aa08b36264b3b779c505a9676593ccccbf79897d72eafcd8f767b6ce7ae0d4bfbe938e1761b967685f490af2ba607a9d7c6a69ee5f238e1bcd7e6273f71511727bc3f5a3d6171b234b3d59f9687b42c56e6169cad96f7272a6a0c4bdfde952c4eb8599cd03b67b96bd602126bf7ac0e13cbd7f6d2b5f1e11299adbe901e621881d9ea07e92186dc7b8861698b48b86534c27dacc91eb9f3f1703d3b9f9558abf9be59ee9ed5ae0524f6fed9208dbd7e7f427ac873d7c6863b7725d08db3d5bd8718e6c8e7c82b83e42510ee187a61fc6a248ee1666518bf9a883b4873f50e132c928e640dfdc2d8cd928a17d29ba551d819cebc99991685931b1ca1d83fa49f1dc860063baf57486d0c3bf9d564ef4ada59a5bba371e9db7138803c119923df433e62f91ca7607932b08c4358beb469f6005120b932588076451f609965d4c606676850822eb44bb543451418d8fab28b0001963b8d3327dde9a28ddc3b581e02557e4c5882a72894a17c959741209652280e45222ca31196f1084b242c63520a4a18c227ccf2a583e511904f0f0f9692a8779674b15d9adce89c5ba944336f70d61e40925e53fa69b3c7afa66787f5b3fe3cb5fda63d92d2775b3a44296d509eb2fa7408d3a41d22b84f67d75e53ab6153c6699a947e7d8fb3c9ac045d43e179452fd64e26fce1def1c032787b17abf7f8d56c3670f79205228337b041ee0d723a1aec6fefaf66bb3300a1ca6ceddab6f7c17669ef18dcdd7846274508c2f11d98290f770f07635d174ddbd6755dbec1ddfd6cc4253b84f390c6dfbd7bffa8121247e9dce91189c32b5dbad3a047959038bc73a577d493d1b3a573f67b0203281df5e2b7dd4c046f2f593a34e79783863bef661cecbd64e95083a56f36e3e0adc6bb41b4ce7e355cc769ca5e83d16f56bb7188c435f49865d11bf18c4259922eb337d4c8ae94b25f118c236c03c71e4822be956a56c25969cbb22ccb328cd6540b3836918107eab524b6520ab0de2e676d504a3528b8ed665503b46c0823b6c022075c2041011134a0450a28a5946698d0761b508e08036b385f66db50b0615c17483865a56ceb522a307c4a600095c0082a8121d4ad88b96b9aa669cfde6d167c83d8b7d3f46d80251b0d6a9a966546afd78b888c0b9c6559961de5742b1ad98e54242a27ba158f926c1811a5524903d8151c4882b152a98461188661a55209c34a4f5c684da9be30f2c59152492b954a5d2cc1a552e9a952690b8213414802dec66dbc5d1811a552a9542a699aa6c96ba52e5460ea946aca92295314710028523002263e4081078a8618ea02c949aabca052f2a24a171af8bc70c28b2446689aa60979a1a4c90b84103344a61d817382234938e288883166d0c3832e8830a219a8a20c20a8e8200b22aa2c09b11d608c8b2f88c09c2802c6a8112f2847241929a1451354e8c0092720f0a9128473a54c6a1b876559b609318366990e294a29a5d408cac51738d79ba053810c8a3046193b36504194ba830ea092f8811341802209438c116639e0620993148e425cf8745c84c006a323a3a22ee386aae6ddd8a0a5ddcd8c868c88b8a09aa55455c828f9e0042b1bb685ceb6c5cea6695ac90721f0369a5201616733a269334aa552a9e4830d78936e434e48754af5839d4d8c53296e74934234b30ceb8116274dca0e119aa669562c51050b3836094a42867b01428d188661580f8830b692811d42473809c1132476404688e1400646b062062f4f27054f8800c4030506318072032b64a045154f4859c1d10a2b4490c59223d9131dc0923842a3500f5e49ccb8d168446bda115764c181232e8e576061440b3070aec734a44ab5986118867981b12ccbb22c8b14c451488b1468a144c5281639726080458b21346d331201319868628c1260f193436484a225704200429665599615e5a0722c30519179502a132204612a62872a2fb80110626460094db280410e68910b4a4528b0385e71450c8a8ed4cd080c1481541404113c70c2103c28c22b383af100179d6dc4e4149da266c7b06358dfede6e399413c319b5dc05876f9ede86f41329b7b60202e607a4c6252a69d74b5b3a2093c582841882c76e8101d1426820c0053e0383eba6081841c2ca8146145069c8053385ab1440b640d580d2b1990028c2a50909469180730cc48c9132348e9c10f84ba08312c8280310e6439381f3001139ea0c4106a4083286c80c5164c4010050b8e573421c78b2ed756c0890542e82009141938220b2822f069628b317ac688010d9e28800536b00112585045cf0d9c28e0b9f68f1aa54e526b337db4082229b4b991371003288c9de366c61352f8d890b22335651c2246908257c87971ce6418e809bb1ab07811c978f1eb4c58ecc857bbcdd69cc1c02802063daff0f3e29cd18e4269328151d20a910978b0bcb5043d2508c2d20241b432ca48c29908667102e9e4c539232344134321ca462e19c21248e1cd6442c7e64612e1054e50e0e206d80c9a38a2cd04068cbc427a9b1bfa9b921234b013d2bb511fd4e6c011c2d0095b0453746014761996695d250330f009bb5494420c2f82427ae36ce184b14500322803e847db3c20dd842a4f33a5dd3e2d90546db0371a742eb18a114a00824e688312b2180a6da211ac48415078a31dd9cc232e7284c29b97209b198a62a01366369882c52bbc79098a1946b5d992c80545000abb971e147be9f438210e0f19e9451b2c854a4c3af003a0d006bb6743a472f34203244821123c8f134a1b2496b1617207cb4d06cb9b79e09b2dca93120085a5ae4233a5d52c90ae82bb4edadc11753c9b1318d065f5a036acd860ee2558bec4e3848a5728371004131c2485f43821cda436869a0db252461964608eeeb049c15a67834c2c81ae82b59b8b18c140ba0ad6345588d918963a150974248cc40006bae8096d6e5047400a63e7b8994d88ab18284faa108aa10dc290812c84c28ee5c539c3dad1ed24e704416177400b279062cc0c2fce99223c64624cc38b73c64607cb431901109677c8c434de9035bc3867e215525c0014368eef2e6bb069a01920e104aff086e3014ff8c3d2610a969df5e29ca161466a6f56889a0c1e1c853fac1ce4b56b38787ee1c5ce0d0e2a4549589dadde6eb4a330760ecda3d6e627bbcdcd8b66f72688fadec2c3b22463c994713015253d300a6727af7d0d1a3362582b18557c716949a14e2c75c5143faf8b912ba96092423d713a6b010ad5f23cf69c9f98314ab1534cbbb4414ae933f9e11025a65412c99e1044ad352dd39022bec44d67aac159bd76c2c7bd709c3c357341786eafade844aaa197d04bc756fbd53eb3d51308f37901b5cf9c99443d432aa18a05bd54aa5a7db0cc96bcb1d882e64c8c312806512d081341ed17d66e2624ade9f34c1f96c52a5772d5b4e72c086bf7566e56993c9b2d6930136a9714a176c996cf821abc995083601785a0caa4a06c49cf6c617f7e35122ba2c788b0a11ea1c6823023ac8bec855b3e6741e0fe8adb82fa59cf9cf1beacc7eb19c2928630240c8981db1bf202f3d424628604f6322132f98d0009126e242f29c32eff19a99fceb7d339b0fb04f7fce994dec9cfc74a196594f184b0748b04315fbacdf6d265f928bd7b778b6c2fdd1f56a42167573e1e62485f463d8f94f9ebc1fde948e90dcd19ef68b6b4d43a84fb9f92065bc8908a3f24e28dfe6744c4d1f78ee6cc67a4f3a7e38414fe8ee0be77e41d1de10eb3e7844f674651bfa00fe8635223ce1f106ef9cd2661790f68c703923a9303918625e28c175b3bb2061971c8f76712717a20bab0c3f8e06e02374fc511476c9ab4d3746c8273639159ba35287970d3dbe1274431170d7471862aa594f36ef276d379cbca81e2f8e5205f2f2c3f6d6389bd76c9bb3151fb59f284a0f64c01cb778e4791494b298463a421dead659c261bf186c490c81c3c7be83002b325bf837bee50497d809ab740e5a9390bca291cbbaf3b9ad8b681115bfd2d4909b88d80b411cd1687a707aaec8eda252f6b6bb0a7122aa0ea33b1a31edc9f4b604732b96615779e68047c93f5ba259fcd25a22b36286d56e1d22b8c1a9b50710463184b6a579e3c3cedcaa525b8a75db9f42a2d6917aba6b0a376c52654e4e03e46a52792764521608c0cdc5fe03c9dc0fd2ea36638c3dd1102282ebde2c7631b9a2d1bb1c9d6bb09cdd665f120c3ec2c1fd94d37ddecdbd09c29e574ab7f3add86661d9af2e67bdbd0b70de17e29a7674a427dbad94bc5acdc6c63e5decd2e78ff6e9e01e7d20bf74b423d23e3dd3c03b872b30bcf365431299c4b4b360fe7d212214164195876d850a660181c9f3801c25d7b5ccde91cfa3a62cd574e68ceb0e665f1909dbb0fd3eb2d52bae9dc2df2d3a374d365cd22ddb3cb9a37d9cf385b33892a9fd40f472a9ae4e00d77d33b957772a0def48d49bca1bdeff1cc192ec9eb9933a5ed2a6f67fae86cddb3e7f3f1d02177697be890fbdc40ed9266abd56a6179cb8de17c972491727754ca4ad3f404776a379c7d3e3ae4dec9306a6412061958e2dc1db52b773b5d52bb3217c42d69570c42bb22933096e07e47a56764d89181fbb1db6957cb3b35507377c4f291d5678f21f6fda8cf8e7d3dc8d0c4753df146bf470a20ce5667f2a6a52f9cbd70d75ed71369e0be1e3a344d9e39c3713c3c4596339a37e4cd35033577472b43eda29f6f507a91b2c4063d90d2214c7ffa6a681872a6eb99ad8e34801169a00ff2826082ecba23e07edc3c233c6dbf7097f2e427bb9e39534a4a1d752acff1cc196e53e152d29c6179eae60d7573e582e60ccbfb5dcf9c61b95cf6ef6695e9decdf52b5c50dde6cd9be9c6d9eae9c1fd8eb3322cd9ce62a046cce291a37d3b0b9698256f537a76eedcb5a9371d27cc5c510d8f9c9ceca59b637abd5e4f67b299dd61c9d7e3842c79593c6437bd4776d3e54dd7e647de1ea6d7fbc27dd3ed6c74ba24dcc70971c2d0c4a33b9aad8ee13452bddf10bf6bdfde1dfba9fbe9dbd138883cbd70890caea773f4b34f246aee8e4a49967b758e5212ee7b497aa6dbd95182fb9ecfdcb6a3c9d31df1744793a73bea8ee62587a4c106c2fd6e67ce784abad5ef90bc25b87f15781950878c0ebc337976787c80828486baa37944e57a2ec7d3e03482e3c1cdf261aa373d86dd996c9120b867b7c92ecb472dbd3e8636dc4b5ff978708f1f0ffbc39299a1c14e5a314a5a797734677a4552494d162794dd5187d4364ec2390bc21d2bbdcb57336b908f62c41bfd3c3130228e7ed7d2d3e3d1a9395bd2bdd0226a2fa15a194f7861792711356743b83fc50d8d8570974d193753c6c1595083fd96ef86c6770e913dce9cda1d7548730627ec77497386867d6f27d220e9cdde4bdeece96c412edeb442e4876cb80b43e2682c6f0746bcd13975f26c7553d5abc0f37447f186103573457863126ff43dbb09c51bfdce6e4136dbb1590fee6f3eb8af6540b8cf15cd191eb3d5dfb65ab9a20eb39bd1f42a12cd206a963d41b8df5199407448b73b7a55968e88735746ad383669c2049c75e0feeae4a4f610ce1812eee78984083b8a37fa4fa8b93bc23d77b07cee8e70a0294083fd764245f5cc9bbec970e8f6421036cfdbb02252a9192a0d78daec61ba75cd9cf236c5b05933338c4eaf6dc4d3e64af3967d35ad7d38442c6596124f6cb63cc6a1726ed1450fb3b5d26a6da4103b3a100ab11f8a7918f625414a6807d425995f4d770d08d5f46c16355833a3ec905806ed0745511ad4a4d4ef7a3adeabc1322a8e67ef55b51e541ccf93c8cbc9669459d439a62745cd93488611bf1a8ca13322c3e35723039206a7c974194ca6ae7b0ccfdfb3779ff574ba7fcfdeabfb0f9fa703c3a7ccf3566180c17a3adecbcbf15ef4190c36e2d2e6bd3c1dd3ed7aba9d186ca72383ed7890f07c87d455e992c8f05e4d65d8999af7d2c91d924ebb3c23ed4a7548accf773cedc2e1e22273a7689754a212451aba4843c797c7f8d22cdfbb293a22895d868a3a29dd949e896118754a92e0f92e68ce7438df7dd90c9a4bda15a7e0799a79f2cb01f5dc09f97c3b24ce5e7de64c23cdd67c0ccf1b0c9d8fccb30a68cecc2d57199e5594a671d8498404f3f9b9a382b94c23c11c864682790c5775197654aaefd8992c7d74faec2da5c1f9db45b74bdff7c52324266020f932baeaa6126fcc9b6c0734c5a85ddfbbcef3408d786ea0b27ad495f884234121766bb0410b8442ecb27a6036d8c56e73f3a3dde6e6c73bcbb7d2ca7142d671c27aa7d1d400d1663f242aea5cfd61f223c5e8eb4edf443a647716ddfe5a4ae7e8299d633e5cd9dc5284509c67153cff628560384f22248a73c75331abe3c1f32de5a85dd10b3cdf547ac25cf1b67d32c69b6bfd88a67c691105feae4e0fbe2734db9d08ce8efab421136b2cfa185e2255c88acc06bbb661cf30ecfbee51a076f7def5f79c3dfbfc6abe6f148b2a311d32b177f9d578c7ec67e3a74377cfb39ae75d43793662adcb3aecda746b9e622cbb44be24134c221b9b9bb8c50a725e21f69bfbf3c2bb585ba0499e607936a1a86f81c5e6b0c0c25fb02cbc85f757c3c23beab1d86885144dbcc22edad48f0255fb0b77e132946ace4f46ab90c1e60dcbf02e56998ef202c3e3570383a6fdc8dc381d7a390c8fe15f17434d66d341a82d9f3886e7d45ffef2c5707f70790c14a831dce50a22201cc3b377f4dbf1ddbce1efa9cb234059762257500132f55c818511b9c48e93208eb4ac0bdc78357f5089d0eedee3ea11e6aa67b6f389377c220dd9a7ea6615cccdaad5355d894bde6312cceaf2080c0c11cf4a6c235f9247f6c8245289cc913a30ab46f23c1b31914d8567d0ccbc57bbb46777e78a1a1bccdf5fdef23c773e1b71ca0e99d8e5382c6d30bfbcbf1c5c1ec3e58780ec661cecf2185cde49cfc56a2e2ed79e65998b8d588be199cdb426862b5f445e2cc530dcd0f8bb320787953a56d41bb78b6815b5e5c60665786e196c0ba75688c42ebcf0164ebf9a17ce62855861390bf68717aefd85d374f782cd5eb859e217bee9707ac1469c49ad859f6c46bdc3bc17ee133a0f596e97a45bf3051b710b9662161bc3f8b5c0828d782aa933c059ee50d4b34b876cd0957a8bfae9d4f8f5f8d14e50593eb0b39ce516f98aa8ac2dac93f53d862c8f61c9c610a3c1d605d63eab6a709ec5be06354f22a02160ede6791485887802ea23a276b15222ed62810dce67b703bade91eefbde7d9ff6cc7bcedef934d80169df41fb0fd981da956d59a6323d7b67b21d50833e5d92eed94d36e2eeabc9b80f878867feee0cba93c7b37307a8892e463fb5d8b8c0130c3ce90d6229013bedeab29b3b2598d53d1a1551c1da2b7b6765669011dac1dacd2e51bcf1532b153110a3eb926825a83f64ff9e81c42962520da4f4149124fbf72eb3de97602d4ef1ed803aa5b6f3be6b16489c027fdfed3aac8a8f88fa0d81ba2b96d5a3648313968e137e3931a95f3fd84ba84a12e88ed0183a3b11efec1c31c5049a02973e24213a0024a4042da6e8810936cf094a0851e939a20658a9c70808293d401ce188206dca0f911019313842055caa67ca112538c11da1138321e5189c2791ce1826a01293810ec8688c1b00153105151a20414a0ba22670a00a8c9a3d3b4e8c4002242745f8811150d48e28870926395018b1020d8917134460040ab012520f94ef0504239e004a124ab2a2095a422a022624451013462831913229a240caa4a041134610b1ed50a3262de800456232a50a2380c05c806000069527e82495b817144a7890b8182ca189922108a1148311514e4f131ab0a00733886a59e7a36949474b981c2dc1d3054f19f608e109b943240515425a46b9984ca87912d9c8104bc2f2954f2704758ef915bb6193c944c368348da6b44b66529948b34abb4e49ed4291d1ae548bcb8b919d233c487a9c589da669a7cd1dda75b4d3e6ce8c358351812ba4a08217fed878d7d19b3d4c35aac23b9b817858bb0a2dd81977c1d2f80d5be32fd81f87d52e63610e83a58fc1aa2e83057fb2dd517685a76c0a6fb1f72e5685bf581b6fd9140a9f39022cd80a2435c37a13a834ec1641148660efd32382bd47108537110a9fd8da9b6db087c2e76f630451b84dd4e0f46e47b1a1a9407190c25d01ec547712cd2b669459d4e09c44f38aaf03faca763e347bee7c90aad0ecdf8759560fec2b5fb936343ab0cbea218638ccd63c4e88134a1c3c68f2d2816737069250d75fcd298beccea2196512add49c09d439e631666368b299fae0e3a90a20ce8ed91fedcaae0cc2ac046a506650ae100c0301716c304b9f06c1274c90e02c7d849292045191440fa622099e22292576278a528461d8744195dfa5248a22a560098238cbb214b63db35d7765cdb2ec3ed1cfbe1bf0b8a58f4cd22e6e49bb4c975eb761dbddd17833d9c672a85d124b2853e8c90b86a44edd9022963aedca92471ae95a314fe24ee2cfca08d6b8eca9b142e39d8cb346c455f6d4b8b2a74149e3661cbcf2952b9d68f089bed73d4befee68ecbd5e0eb5abb1bc849294d333a61d19a55d518a2992b09c82a594af293c80915c9084b32403cb30cbdac5264a8480e5a5119b0c0323c0dbbd124a0fb5a066d94323985df66422187b04330dbbc4de239d681703be9aecfe68505ef2b44b5e2269d7b10c2272827d90b2c05d845d9e00677248ce8bbde5fef8a09ebabc049a337d1fa8a76491a66537cb309c1efdd4b1dba3e52ed7c60607a787cb53d7e607bbcde92ec76e0f1b96ab7c5236866dfba9fb68b9cb2de2f216978b13b6bc48caa5e531646197c583cb53f7e1f2d42df2d383e5aa1739dde53e544f3d758bb02ce0e5a99365692c96a5b95816f619c709559685dde538618b65656d59d9e759dec1c468318739ebab67e9c3dade5d7be76267b06c9cadec6619c4cabe3a4e086359d959c7093bdb83e5f39be581e5f39a959ff46950dec80749aa24a1e7f50a59d8638e13b2b0c31c278489c15aeef296bbb056aaf755cfd2072754a9827c583e64d897613f86457e7a8445602e0b7bea2f575d16767dbc3cf5976bf3c3e2f1f21e62f8727d64494a881182100cbd5e363a1dbefce695ba6ab6e45c82c40bb0c062cacb0d22ab5a2c4ee8e222df12e4934a3df57e86819e19a6ec8f58b4cd168b8744c2162744a16c9cad5914801ca13086323c5970b6e459ac04b1976a03d52c87767eb02677b2976adf1cfafac972a8087b29016b374ba3a112f6f8d5d8342839285dce0fe703de8e5949a4c58e28cb5ebad469d7cab32c9346599649230d4aeef1aba95cce4f77221e7ada86b573570ed9eddbad57e26ee54a1deffe38b572c8ca1db263974caaec691776a27645a9d3e04ee7c0ae9c3eb325ef108cda385bb3f5223284a44c0709a541f927fa997d42e761dfa667faf244da55ba916e65121389a52b755650255183b241f9a982aa5d960e1b1a94cf3a8a84a4886268e8c76cc96ff5c79c9157c496fc0db4c05272816511962f551fdc18bb7228de909f3f354b9fa120a02e7056491f9937f98eb27accf73c4e48af2c9243b3251f8f700403b37c74917923c6c2c26e1030f0dbb27c7491f9ef070f568f8903cd6cc9be9268b6b69051a8f4fa70bc9b89233102e874d1464b6c6768505e1d574666eac0b24fedcab48bd58f58fe180770763388bd6277567ae7ad94b6133a9944e38d0e8f4cc2fd802eda795b5d17238dae8b7582e1cfecba09a9bb2d3179626cc10550069489e1118fc29f49e5064406b7ca039188c64824bbc1f9eafa94c648b71a3a638c194823d1bd6c644e2403a7a40d28112a8b121dc08e6049d4bc610ed4bc618d28fc991608cfb7cd1a11eed32254201a119eb34d7209a4da7fe26626853fd446075323d4096426614a698d9408951ea1769cadd85286294e2005cb5729a534001dc1abcad084d25301151e522db0e1be382de5ab6b1b6005e586f30d9697c61b9b4fcd9bf744cd5b3c4dcb4b318d37aa096acb38354ddbb652a9c4498ee3b6af467e9b82260e954ae7382e7627bbaecb388eeb66096aaeb8eb6ae225ea9cf0477a29da0d2485e7f564ecd2d77d359ebcf7d5f4bdaf46be6d134e38e1449d4dd4ece1a89232ca95959588dd5a63fa6ed0566cc0f12b5f8d900c8b8c5dbf9a583d1696d309854ab5d01653c6c124a899e2d3e9d4a1bcd38742a1bc54eaab914f7d35f1d616193b959254707c2ade78e22622853ff12d5f8d6cf96a46505d5c5c5ebe9af8f232038e57e9c0f12a1919230c0ccc6ab5aa35ac78037bf154dfcb8ba752a954a998d8536383f2664fc656a9be9a0ae3c1c078de1337aaf0277ef5d5c8afbe9a783d950af73d162b2666c68c151a34620d59635b42044c84606522a939b544cddea66577f5adbc55b7e256abd56a55da56abd56ad5320513ce94359c744d71830dde06288fe8a9a2c677524ad9a69af3d397a77344bb1d19aa454456d4bcedf4e5bb96ddfd6da7b7231bcfc6d3a07cde7676369e76c5ced976da45af3dc6775f8da8af16a541f95945cd154b7a59b1bb39b287bbf16a43ed921a14ac156119d4c9581b933845738018ed08cb6717746039059612dbb423232aed8a3ed0323b7127bdcc36eea626630e14b7a4719ab6230d6e3b0dca9cfb9335a41d2caf19b54b5e9bd2ae572701e74d076b481a1296076b6f3d4d3b2b68404b5aa9b46d32cc2c265bce79a413d22f5c7ab4914b3b78c33ecc19563c761c56bc3dfe7ddf65451b7a79591127dc86bed265d07667955b83db395b676bbbc9c639f4dd79eb9d55debe492a2bb2e265c5d31edde97d78c7b08e153f4462d67c0ff9ef7d8959f14530160fdfe57b7c457ee2ed613af622dfe58bfcf4ed817541f874ee2b4733a72b83b6be2b37ce56bc59a5da64d09cf96c6ddfb65cb72a0d6ea59c06b7794baf06b7924ee7d872e9356764b8cdf8965ba767b6b6ff46abd3b02b9f615d1e6359ceb2f52b8b3a8c3dfdc5b69cb3a9c78f35699a868de10c1bc3181b43ae67fba6e3237bb6ec6e490d6e8f7743da90f06663d86129a8391ae1cd0455c342e82663f0c9a078633bd5c189cc999fbe2c5f794ebdcbe365cdcb4345bfdd874760ce70dfb05f56fccb71b6cb8a97c5c3cae963bc3d5cfe726dea5d6ec3f295e36c742a5183220dadd2a2de006fbf026f8f374b2678dbe29ce9a6274b10699078e3817ee53de857e4e9fbf6e0ee726db0c790fb2eefc374ec1659b9e9f216f9e9b172d38bc87fe791d3f214ea2796d71c7ace010d6e747bb5db59ecf6938d733bcaa66c9cdb5b6c528b8d61cac610656378b23164b131ac5c041adcded78706b74f236abe118b07f9ef3fe4f71f2bf43de4e9b5f9e9dbbc6f0f7aeedc668a21f78e5a6941569f1e27b461f565f1208fbd87b4f9e9abc2ae149aaded369737a441b3b519a97d213b24de21ef9dc58364f990c78e5d5edbe26c3d5eb5bdc6e3ed9e8d71b6aecc6cc5c6d1c6767f28b5e0749f36906174dac8eea4934e4ae333bd20767fb0521a7ba8c350a065d846b98de34a942b6d34c656b7fa98adb1d5f4062182e9e99d3713874e2ad4451b1933c2b31bc330ecd38812614699fc59b113d40c67d7a76679845b5ef92959520d7a0d62c7ee346ab085c87823dec08c8cd0451b7913c2d9667b6c76a33bf0be3d933e522b713273c6bbd9dd58b49b6b5565a1d499db16762cdba79da6813498b24965d9737e68cb2712359361b67a16b36749c47a963caa67d903f32c7d5c9e25d0cb5976fbcab21cc6a2aeb2a757cbd2ba95bb787fb1dfe347d3ac18c2d818aa6c0c5f6c0c5daa8d61c7830867cf9e63118f3913c3ace54e80de081c35b675e92cf731dfb7487f9e65b29458ecd67195c79c61692ffd98332cefee837b897bc715e1ce72595af6ce7eb6b22c33d260268d8837b2c78fa6a90eaafc57138495fa292083d06ba7518450256a963a4150df9e733acbe965a52e0feeb2e8bbe384a5cba297c5c3f6ee299d4843e34c9e0067720438931fc099dc0036419d5808c53912f58834d0674f409c9146c456f64c6ee007387b7679a54ebc911d2b41ddce72fa8e7e2c1ef53dc4b0ded251f79142cf0aac2823acd7a6fef4f8613cba6bf393baa8eedb23eec15d9bd365692c2c1e4adfeea3f4ed16f9e9d1af2f325fba2ccd473dcb2dd2af97a5dd1e629893b3f29cef39dd4bcf313dc77b0ef7ed31dc4ed33d1accb2976c76ce66ef7c70760f0867ff8270769310cebe628770f6c5b0b331e46c0ca5ce6c653f2e8f06b3ecd388ca23677eeb1b0fa7698dd2693a3aefdd71a567d0b3d17bdfb31da6491dac3d4722ac65b66e5139ed07272c599c304947264d16d418f6b77fb6b4b751ddaccc6c69ef2e2aabc7b7dbafd9d29e65b076cd86767f983d7fbad8ae186fa632d9a473c68373ce8b550cfb1667b46397d2379d94d2033428df376ff1f3468b438312cf190bd0a0bc7dec469abed807329a655886d1db00b1d481e5508412896294c79694892d49135bf259478d2deb45708b3482f274471492c1f40699c02bc66e9009608a83d8608a61ec06b1c194dee9614dabdc4667b1e71b4c40cd32323a6ca0e9ae3974ce1a914010039c55f1065deca6a9067f2c205188603fcf701870cce0a69da06e1687d9eaaf106582449939f3630269d77dcd16100fcf0ba4c1be03906ac4394e399e1467f9ca40ddb094d9644ecfd4b0df5f8df6630244fa38080d7d8603b0d479591986e7e9737eb4ae4acdf138f06857c45d8990bc8098b971cc6e0ed9bf1b6ca86e5073c5cdda621a9471e847370e9d3732ea4ed65a083a1c1aeccf60ab41c205b11571bc8db701b62bde78c137d80727206bd0328c6e5a86514a8df014294793d226088997df5e38662f1ced10896f90381e20ca8b038fced1d7806abeb682ea8076e588d4a3676a906822b622eee370801a245210a5c8f704640dd9fb42e40c76fa1c992083c02d5bf259da88e3a2105bfd1664a80070c18f371a05b54ec06b82107a809e9147dd8aefe3d0ae7e4d49c2f1394ac971a8e71ca313e2bd30f668234fa0c65dac947b96984d61f7599ebe93d6ca6bf80739e59577469ceb9c9161eb4889048c7135bb3f524aeccaa4197bc4cf9694728baa3d913d7e3ffad583fbf7efda7897bbac1e5b77e591ec4e7e3ee26c698f5f0f32dc3e5bdc359cf0a5f7d783bb766db47337ce56964638cb233c2f91be1e64983d7e3cc870bbaad9a207678b5eb3ac1e311e27ec92a4109ecfad8367105986349a33b2e868ce48a2d9429a3372a84a0dcc8a9fe0c1431abffb7d591bc6c15d864c6a9d12e0a4243a81e4cdc499b43445f7181b3255e3ad01e2c9292552986b96c131aae6718cdd4aea256d0d1a3362582b18d58b4b4b0a7562a92ba6cfebb8d2a665189d2de38d7e62c6beb127135db491a59013356f581a01e3a828bcc99c280a3b0ee1e08b1fe88437a59c1e56766da214af293be10d4684574873c003c413de644890423a0396c7993259932f98f0843637357a42ec37db0f7842fa2c7be9da4429449081a4b0f4ecb27c64f79e5d1bb9f30224f88436d96fb0318e427aefdac41caca068282c5d9becdeac108537d8173c21bd3894d2538ac4054873624d54f9194495aa96592035218a4393880546548818003184c92452d0039451b10514495a0e52f083b451f103c45149074d14715644d10123313c8004466ed20c4071e4514c054b2489114507b321083008dab2e9d568efa4cd356f586a975f8d7667f76987503182000a6de86fa40eb6000a7fb8e3849d8d4256e6b5bbec4e67908983c46ddb485033109984b94de28873e6450c2e5e1193dbb5b150a6cc206a6cb073bca678b193ea1c523e110411445163f9a0c74eaf8df4620326380a6f568842aa833194f884372f4132581a418a902cd16b83726268881e3b4eb8cd1637430e50d084507883c1a087278c9d039331d3b01154210feba971b65e9e308425ec843313a2090e08853731ca0c6410ea70a1cdf68a6238514528ec308a69f1c6164478be81e64c8ecfb87dd6edc3e4b82c6c5beb5e20cff68a1a09a19fcdc732d86c5245ac7aa7b2b2ae76788f79fc56ab3b04c3defbbbc17bcc55d1236de94e0ff52ee5f1a266ba83a7d7453d3dd32423252b96e73d91e35ccdf959dd1f3e748e4f286a0526fe8175d459af573dd5d2b275abe5299b2b6e41a18ef2ec4baae5a64e335f605aceea50acd376a1ce7a4c8c75f9c93e41e3a81bbbc5627d46cab25a7008225bce7afc5a725c06e4b03164b1ee0f251589855b6febdecbe3c6a3d782b9cbcd14bb3c86194ed30c88a169aee67aef393fab13f190c6f7ec3de652237a34a5de7ba646b8fe07efd2a34b8dea147a44bf9a182ca6aeec0f1fb8a8a853ccfbab69545f788e45db940186c7cca2ea1df368d7c4a1f32c0f2254ef390e1d80c76a6e514d377df50375fa71d4fde9bee5b6b4dc0e6a2020d4d573afe60faa91ea71cee8467a79eae60dbf5cdebca12eebe67aba59855fde72b3ea74a951bc317f92128b7cf0821e4c2de8947bd439e6fb8b5954255ebda341accf37ceac7b37b73ce53de627fb83f798779ecd129fde492fc69e3ebf1daba31ebf1c5647b5dc218d4f377bb780c4a7a71e63593f5956c7a271aaa467685c96f71832a05bf3a9cbf24eb117453364e0013cc348f54e7aacd4a5b3a8365e7df2a0ae9e29109d9ff7469ae1b37ebec968970caf76c590a31369f04ecf8d713cc61a2891c4318fe3d8bb582991aca181248ef99969a5e1fdd42c2956cb291929d6ddd19895a247d80bd3c18e60482812ab2505d4ae4c7bb0126a3483a5532a15245a0548d610230e994f99e7c6b981bc4b93e28df91d9c7c4059063438bd138d9bf31313e3dd4e8ab18da483ba8ad99c2da3d4d58d0dba9ca65dec8dbf582152c666181c36c3e0176c6e32f0fc0c6a34a4b1f71b3759160d2e40eb348dc3e4d165d4472124afa991a7ba798b0c68593aa55b5ecbc6f0c68d4bdb8bbaba3efc6870e6a0c6bbd082a50dbab05640a1563ee0d36af5e9c57831313137af8eba8db45aad9efaca76528313b55a61852885507cba403300c2636cf601c7789ee7ad56312afc6457b867538fb1292babb76385afdefdddb0c2577785155e1393ea2a0dce9497c23b1b7cf25ca867efa9db489d673bc97b5759c10c69dcd29eeda496066a57cbe7aa93da15f1aa57431ab79ca61f01a31d9ce38f93c73add1d8d4f3f1870a473a4673a2007b42b5e01c508cf24ba73059426e02c5f57d80049ac82e74f2b6f47cb57384d671cbc72b2832a38e6a877edad602356c14a0cfad0ae156e9678854f1acf5beb31ceb0f0acc2ab15aec259b031b65ad63b0d1b63abc33cd032a04115ec0f1cd4159e63d10d0c6870e621185edde5fded10f3d53d7bba99e2f8ed48ddfb0a56e21f0ce8993a572aac54506185bacb5538fd6a54b8b2ca17eee2c97a37537c3a7d65b30d5e5d7e35ab94cdab3ba471cb65ed90f8e53167e5d0f298b73ce6a77730f6f4ae4b7d65533628d43ddd9bdf0e31479d7e3bc43c75330e5e1d65e70deaea31f74e1fd238260675330e465154ea9ecd97b4b7e9d18aa532bc7a5661ef71f51c833def343308111c73fa4ac31907c7a06c100dc79caeacdec9c3bc9863df0d3131a7f81473a3f9eca85ddd332a78e60c29ab82679684674606d65e393ada4ebf70c429dc9f1c8bb08dfb73a44c93a891370466c5d8cdc29cc5badcda98b758ef28d8d3afbd21e2d45fec0d11a3eebb58578facc7af66759a46c1663e18195815168b19ad584c4a4b8ff57a78708e459502cdd67c0335385b4903cd2c6a6e20395f9ee7bd913c6fc6b12aed8ab924ca72480ac9a0974c8d6080b0a423784603c100dd9b55f8e626c2f3e62ec2f3dedc4778566957e3d93826e360ef2b54cc59a8bba331ea2719f18c4c028852392aa247d80b1b5ab2049c311dec0845429d625a8ead8e7d352d97127d35ab4ba3c058e96265ca4a2ab24a8333c622c5066bccafc6c3de29d09ca1711ab462d1b80d746383a66fe59ec77ade5e9e6bcbf3339865b20ebc7a8c39ccea1d8c6551bd8bb154652910a53408c6d6af6620c1338cf08cc776ad3e23e60d14633b28e64a6e23207e853467bc7b670161ef2f8f73c6bbcbe39cf1def23867bca71ebda3bc9fce8333c5de0a0609f64c57d90dbf58a40ce2dc485906e746ca3a706e240ab462bd9bde1d0444833e5a64833aa1d44c89b091a5532c3da254344b9168159ad420194f2a86e3500c46803335d288b86679b2084834cd054ecabb6d923b66398ec3bc1917ba25d335d2cd53c964169c4eaaf60c9ea64dcf369fa5c1304fda40bf9a8eb3254bf3d56c57c715351f37cdcc8e35ed0289c132931288c13668bc0d55cad364d0455795977ba62f515cc2b67e296ef16a364baf5d598c5708c54326ee6662be98f0a276180bc3b2eeee96c1dddd54706399946957ae2d756c36f4dcac8e4e7a9946d3c74edb3564d2581d6154f9ac8346103b8845102bdd8576956eb6c1197641fae540718683311d36d0744bcad2019b38bb2e744c832dffc2bae8a20de9357d7f3532b6a9dfc5c8fe2695aa78439a78fce84145f5c101ed1222b10a4b49238d8490032c233f23ce94a22ad220b13c4c74d11ec4c0892ab0f4e28c8c4b07464b738606e59ca9bac939279db7e9e90c209ef49a26433fe9dce6b66d57a6411d33d01a33803a1a9432584a1ded92320d4a6a6a99a9a35d1169eb0f0853a63c9a65d9bf59dae8cd40c039c5636bfea59b55f8be7f6c78db6ef601fb7238a6a7991910709300b835f58010d65e390d6af11d0ca6413862fa95d374ad2b916e5f900df5ee069f386a2ba5f7f45aad6fee849a5eb5d367c6575724ee1ae74c1b71b7063e383e99c1148c03c727345802aec10db000e8b57a7a7f355fcde9769222db5188725035eddcb79ea971e5e5e59c7da15747fac821620061e93a32dc4e6b5228d44cd25646479068848760f8648339971b4e3737f7b634363f3dfaf4dad0f7e5315bda6d841c9bb89f6c504d374814c2df23c5dc353de22f13c1f50998bb8b0d223177bbf65233c2b631ecdaeb53feb894959893a8171e8261ee4e20161cd42440dd8a559db3a7c7ca49ef05b3a8b8c7d8ae58b3c2992ebf1af9d548ee5dacf5d1745bc90cd59471f089c548e69decea9f65396701d65797df0e2ce7ee0fdc591e7fe0fedd957f36dbe0cf02a80f49dd74e9b703cb4d2c9f9cc5c1dfea36480dfc03eb11a36c901a98f515fb5d8957efaf06e627db3ded84657d319dd464d8d334f7ef8482e9f574d35fcebd9cfb7eeabc58bbafa6c6bbaf66c69d93a77bf277ce74eee6ef520007a35edf71a8575beff2ef1e0addb783e9b5568bbac94e173b794e3b9c8e3a87e2587250f3d4c1daf3e4f95cde9dbe1a179369eab4abc6b54f23ed9a71ed73e774d3a9c6396eab81fa6a6a5c59bf1a9fe99b71d377c38c19d766445c8362ce461cb93b5fde7d283c31af7a3967facbbbd44f379f2e6f363d9f2e0570f08c7f48f0ca4ddf593a48ac5d62edb2fe1a77a9a9afd7644fa8a77efafc7658b9e966ee2bef6f87efa89bb967d3bfd3cc93cd363f983ea37ec6cda65a673cd2885f0d8dd37487028f3e0adab7848c19f4e02896e0f864498e0ac72733b802afdcf4e9a37d26d13e83e692120a05145057880ff9be0f7a296f1179fa2236f2fed838ea287cc5460abf4fe12944dca16ca06c1c65038582f6d5dc771de783fea7a250f5a8d73a63c6abcb517835994ed395e3bcf89d6ec6c13dc4b04d36db60d363bb7e78a21fb1e9d5d4759d17bf1b566e9678e5c7c41df5d8026099ae101ff494de22f4312c6243ef8fe9fd18a2cef2edf09d7b67b228fc3e7e35f7a61a47e1261dea51b83facbcd2ccb6315cb111a36cb6c1d93e75cec68f4380cb4d347d6d27591d6abcde8c836bbcf4d59cec234edda6ac67bdd365fdea50e32eaf71e7abf1e9b993668e7838ffbd7e35dfc99e9cd4a7deb17c35a9f8d59cfe7d0dd4b5fbec8cbb5889e5877afc7238dd8c834fafff62f73cfb76589971ce5200079f1e3f04d49f7efa6a665c59b919dcc7d1f8f7dd4083c669dc2c31ea9df468d88867ec80fae9e67a7b4983da5143b3a53d652976919f8fa2d9d24ed3f2db412b83a8416dc5a2839adb48680ad111109576e54682b56bb97b709576e55e8235a22e9a3341f487e68c50bba2e9dc6db11907c73c7e3cc4b087343ebd814ef787d3b9db410d6a3b70ff4c37dd4c011cfcdd1cf3d36d24edd34bda15735bae9d6602f5cc99e9137b4ca676a2def47c7ac7693fd9e9d3a076ef08f53ba7754f83daab1dd2f8e3bce93393e088237e128511ccfd87ef1177262fce191f664b3b61514b3bb3a569ef28a55f4d3dfd6a56aeb2117799b73a3da9119f3e934c9f769dae9d4edb7703f720b30cfad570f787efdcb50f01df6d9f9b1b4983da5d1e2bc79de52cff9e1b88e33e7b72525337bdfbbe1a53fc6a60beb344a972e555fbee7d35df95959e6ce34e7a270be4bbe95dfc503f590b487cfa67817cff8eb23a4c20a6b382487cbac49fc427cbfa27bb4dac0b81d860ea342d31cc235eadaeac302b1818161696ef11ab5457d64ff57d2f2f2f97a583c42e97d8e566895bee0f2ce7de48dac5820096d7cfaf867b4cdd7e35c852eb5756bef2d5d4af7c352bf9bbdca90da233c5a79b6ca60278f5e9cd899dc374221ed29f4ebf1cf277eedc69a6c956fac3d24162d32536fd64f30fa8366a176aca77edf48851ffbe1ad495f5843afdc321e2d3ddbe1bbe0799655c960e983bcb6d9d06b5de6950fb8aed230d36cf0ed6389628552635a8fdbb12e9a84110d49e7b475669507bbfb0f67e754ea9b4b94cf7890d09a94a37a52c38a8591a61edd2a85ddcb5cb29da630b803b6d0178e7beb500741e76e7eeb500ba73efbe1a2e7e35427ac8cf6b63232720af901e622875664bd3bc6b8f616b9ef6aed3eed91eed40b3a57d8b616b3f61a1bd9bd32bd9ec9bc52e3f1e622885664b3bf63e7d7f3c7224d16c69a796c5b56571a7cfb2cbe291bd871866f72143ec32c4ee5d16f7cbe2e87dc8a97df6e5616e1a47e610a38b9f32dac6524a29a594524a69c3ca28656cf95e42176d74dbd46143048614008c526444456b09bab0b577699ff0ae0bdd9a9759f6016b9769972ce5dae96869652c38842a9fc11b5c6870ea9833f3ef7460eee67a1d786ea75f8dbccfc0766d9f7721e26e7e35db1d82e1defab274c82c8061eddab8f46f17c5a87c953aa3c1124c083d41d26e0c76777777776b19b5d1387e32251d20788f334e946dc26ecf96474aa28b61a41d4b5e9b7e0c435e3e8671da0e03cbc7df5085123c5528b1537a61f9ee678b097fb07ed75d2c668fdb353b83b4296768b730ac850189699b43c4c31fec661c8c35d613066de405ced26808d39e489df301ea1cf2138a9a5d7be9ddbbcc72efbaad44f482aa437633766dc8c45ceaca24dd9229ed663e1856ba591a0df5ed2e96a4c1beaf327096464398500870c7a865324983d99540d247faf84ca0899d7659cce43465989671a52edb2cc55dcfd88d3bbac9d8da3aba31e007111b0c8b4454e02c85b02b6950be481a0d659f4a6050b6b612a8831a94b16e5b0b615104ee408cbdb465dfdec9a14d3b4d6f9b4ab541e92e90a71ea8a44af4f6d128271953442292000004a314003030180e894503f27822a8ca3e14800c91b658724c17864110831042c6184008000000000022300243c609802a598d551b641ee87a7f52e0bd36e77bfb45d92b65c49905768bf85e5f39779001ca2140e2cb1bb5070624d4ee7501a7d4e2f8a4c68815c79ad693ab1194d07c8ca6d467341a5c0f6c0520c7be240a23bebcef2c54790985185c79a8604012e881ba001a5d2fbc7a8b05f96c4cca84313587b2c809cce1ae1f8c7fa504666a7e3717cf6a4ddb49ca40cc427f897503a67905e84ddde7e2ba29231f565b2db92ba78c7837e4e1a2277cf66a426c72d13f2fce19f81af16be060a0dac87224a82a431989d89b24dc9e57ed50a1959ff11fd01dfb0fdbd17c455221008983c5563bef0c03fc9860d2cf545fe75d235df4a46554748ce15793c73aff7aa761d4111d0fcfcfe76e2f1459e98454a55bca1b2c6975512c7f8f7765a70232d20949e71388dea9a397510724c3491ddaf78236328edc3ff8177cf981d49245420c459270c41676010b340cb662074614be096fb6038c4ce1093d363180635f54d996548237d0c76d04435bfae82b7a15bac748867d02d4f4734037815bbaf615236c6e7695dae9a88dd707820781634da23fa1369846e4e47bb93d5588f44601e8a34c7bc8495605d4d5bdb0975e26c33f17a9cd25fa5a906369b1217e844110680c3a360f5e4617e3af35e84be91fe47a0d8df55039d9965974c1dd00aa8b4d8d4e1554e582265a3387d81675da5f5355c825ed92ebcc932dbec66c8607c9acbd329a625c930055dd95dc1928192df5dd4e340b6ea5d2c2f194b8f3d186db41222314c559eed75bb6b9a034d38fe9efd81352db726d8b33a6711474b63f882c552ed6e648365297dc29a57b1990a8072d0120ff38e713e776fb3b0ca57b97fe15464c26e3c8a00eaadffbf011c4c4448ebc368ed5fe432632246c4cbc0ab434a1a0810bba50978554c5d1e52305d4c627ff4d2e023d0b7baaeba36a84deed17d2e661fab287b4653dc3ffcea30615038722cb0771dd5b66c8768c7ee5ee1b478fb072e615faf0713dfa4d419b63e848f54abc2ea87f5a8e147a44f8eabea65918777a7958ff06282b90131a8ca90e128b3d2b54c203db9abc56b324a2e5b7b1c55c44253c0f7eda75a0f8a074be9405866eef2f781d8b602d1fa50381d3153320e71d2bc048e1f2aaec448ed4a71f8537627327d13b2f0e3ac6585a857fe7f69b438eecf7e12ec25fa002db041fcc23acf982e8c895d87bc8c20c6ca7c514b89047814092b84430d2a9659b0d940719cb953e3f75cc15be8efa209b11405c4d10bc79e0216eefdb081f76a1b7b83b1edfd4e1d055fb39cd650a4d8631fa3076ff85df4c9a1644833cc74611d2188fd42f303696248281a76241318b329f4d0384ab679fb93363786b997dea90b6e3cf2682913fc6caff5124727df9dab64e0b510958c5ffda6c230a339811d4808a60792a220630539d42e31260694ee932ea2fa97b5762c31494161b12000fe9e6c22a7296f88e5eb086e4f3694f48510d579767a39840e69137aa64e780782be44d53287340d9992aba4ffa8e7ef2b1930f1abce9e210763e21df2ac44a2755f203e1c553c8ba100109aa2b16d34812f45901f0a7ebbc8f7cbbcb04a1e0ac2790a0a598d823049427f87472705207ed4554aa583a1413011d654ac23d09c8699dd1e7cd13220dacb5e1c9cfd5d6f7c4240eae0320422f16b132d499c63585551f801982479d6fac6e29cbde4a1366536ac30e53bdfcb5d46e528e5f8fb7c28ea79f913252f72ca285b2f8f1f1b34c473010a5a0babacbbcdd0346abb919029d5be7b8e28cbd40f3e12ee5c4ae1c4c377f100873e198cf7cc1dfc4c4a464f29d23b22ae43a5ee425c6eb05f08e8326040a711df42a2ba040378d314110102149644238199998204337dbea94977cc9f5471f4338db055d446599ac1462edea31133e4daa21614e524d774316f7a98d689dabf188b5c7422be788cc632749620bca4550d06acda0687c4cda4c4877ec41744c70964ffb070ab0b8851f68a22fceb9eda5d34fa80d7d69cd73db9ff8b303d080d4bb74a578085d3662eaa0e3c6b89728dc05e87f2dc101c6c28c829910aa37e200f0efeb9d3f7b9deff1143eafdc9929ea628a8406e8e649f08c7f9df7339450cacb39f5e185b728f66e5a28fd7dfca48190dc6ffd72613b19a8a377ca0f6c7ec6cbb200baa2c5794a1a4dd3301a9a4d14287a37ad436bd810fbe2f4f6262da82ebf5424d3bff499f462c96881cac0b86c273a807021a2abe5891e4335fc6652553d2617005d6185f1fe375a1671b4ff64813f55d503436b321291aff32f15fe937bcdce392058d32b1777ec78c4327e904aa0cb0420ff3ea5b064d2bc4624d0b24abb0f9378ebd07f2a23527b83b83121a77e5a65448a5b5eba0a8d2c683f0ac980558be4bdc9741f8ec22eea6328c4eed05f420c1269b64afa8777e262ec95471df7e20aed1538455efbb06c86127ca8254a4ad51f0d7968a8ac3500e247e8f9d4d153e35a4fc459c37b046e08c2c705d096471e6abf889bf4fe8b20bd19c07b1abdafd629a4457d5e2250a4508efbb10e9ae27cabe029f2ae6c62a3fadf07dcea680e7ea929fec0931f2c944fb9ce6e9174637ee2fde76d1236b98477724f2f5c62ea6c3d7b485c8e28f7339f2535f31b747f9b1238c86a231f09ef92bc996da578d45d715fe249e8db27d483273a9d966a28f2e09cf6c0f189219a8a0495489892f8ee59828986f57e163474a206c1fcfcfd01d64165f14a796603cb5f5ce4b4348f68881920471c094745e852064f903da5601f63e43b692dc18aa15edb2980e4f97f4bfb8ea7952e5286d8f89af566bd8cb76a619b9def22057b205833c2edc8e6efe9a27856fd5e5aa27069368af843a2004ae588b52f3f37c146cd8d69a7fbbec62ddb78db9976c3f426838fb0a4f32dfed981c4f3b1bf2a18880e1804496993d37b254c7bd08f36c545079fd5c319d27a24e3fdeac3983829597f79fb2a299fd2211dc6f87bdbcd977e1cec46916a6745e5e6c37df0d2c114440f314736cc2a32edf220fb6d11752d5c91eb5eabefdae43a4409d3fcb457ac83f32f0beb210ced6621b9e9eaadb4d8792a856ad4c265484d19261b81f191e5b41591a023c5db4502999625d401459c1922c4648c4eb353116ae20b3253d8be20079d83e0896536273f44896daf5f2f35bd8e6d9c9d5add27a40f3c53088073a4d2687d7d8b308a990bf11e4acac0a18c4aa2e8ee8621500be425dd97c0630493666fa37efcfb35742ad46ce315eecaff7394bf639f779cf6dfa24c2b834b696ba820a641cb5b3dcda1061bff76289b99ef91f0da357436196ffc8be704780c33067add9be6d14db08445141d2e461ba157089411ec765e77571a48df33d213ea15f6ebdde2e4851ce246253ccde41fcc523105ff0698c358decc302623d0705f3a2e4260c52629a73d126a49146cb3a8620aa8146137c489ab966c47293cad29b24e593faa29822d03819b894b3a129cd2eddf13599e82bdcfbd473544df8108043df7afe5d271d75f6c3c222b178036d440dc25e5ba302d2e48891ec05da09a9a74a4ec72591778ad2918c65db95dd9813bd9647fe9d1afc2a7c159d0d8885846896ca7fd8211b00e4756da166648938fbb2cdca986ccd84cd70e64fd2f7c09cdbafdd38df2fbaa50e51cb1b2f9fcd979e03827417bf1fe4e00cadb1a0d6a5e30c92b43f1751a1284866e05996de3e8ed95adc1309d81f4662dd2bd38cd3be445a6a5503e6d58197dff004069ae0d157ac70e751f2aa4c480086698cfe0822f6129b6e2f7739f860d6e007d19865abd029224f24ea6091f3675c266afe0d70c7df6bcec51c79f5a59c1410be3f11e11204b500d1eb6640dd79d568455ab0e8933b6f43b1b323dd512d59efaf783a64e32424ae7dab98024c5da5c8b21e7650492e181ed15404fc0ba18b5929803035174ad2abaed665fcedef9b395a34debf957f695a58217b403e1158a0c3b40f0479adb5f5adfaeccfbd18acd09f05babc2ae1fb9c9751948a0fa302fd26142fcd579829fdf516dc5d025246e95f894ed3c81410731d748b3cb95bc3696431c4892efd93093bde0015d982ca72a16681ae471f24bb0130df03eb96c1b8e1d97b023aee3736ceac198f888b0bfa2957cb295322c5f171866a96e643cb0ccb5f9de251b763335a4e1eda74ebb75f5f30d42032763840c8942cf16cda3257313179d3dca65d4f92054f8b6d0f2eb888252edbbf2584e5b623945406eda10dce7e3c64d213dbd1f526307baf8113247b3b7d3902d3cdeddc6f9fa6947d1327e075f5dfbdb62eeead9d996d565d0bf75ee6057af0c233809c9bea546cb4c0215ef0cd659f16e771eccf9661d80e4084dcc4bd0d1b35ffb84714f895ff187f25e761fdacbb8fa0515cc1b82c7dd6ba87d17aca8edc4920a0dece342c2a329d3d726c300795794bd28b70a22988c00b0b431b47461dec1f9079a71985c97a285a4aea7a52eedb54d1965653c4c07d428327cc301f8ab63987747786b8934dcb517bd88db1ce7cba385ec65500d89ec6b4885eca8c3222e7e7ee8e3df6f165a67f6b6f644f365ed8e15cc31d3bfcbb3cad2f7506b48471b5445350780cbaa6227b7662af83e067d80c1b0a4e6e46e3ac74d64d4ee657ac02940007bf50f1c98faaaf1620cea6ac8a42827aed2b767cdf7b2d3b357b364f615c0aed12286d2a98a9fa492d3e6418e52fef66568035ca0c8a6f8de76d458d545f1e96417594f1171fa54b17f34fbffefb6d0427d7fe7acaee4fd30c53787239e7c1ca8ee2ed191dab15aba368bd9b1f6499af85a4666081a67bceaf8b2827c0e36b52ad897ed9d4ceea5f4698bea0e0548aca1bf81ed3b32d8f40dbac94210e6d33045dfe396b93682ca7c97bead5e46d92f55681d5b73ae22d4165b94506511107211ab028c7dd0c286397cccbd5f3341d40f480424be9754bb0122708c3b2d7d037647406534899a2f30139ceec529b11e0d2efdd0e168f9ac83276ed042f8bab908d4fcc9d33535b14ab4524448ba6f27bc6bfe2cc34b05edad9fc07090e709cf21d1c650edf43cac8119d6702a8af351fb444934ccf8172c641994cc7bff490920e89e29b41696fa4413832a0123763e4b462e8ffcee25a1d90b15baef47d333aefbcdcaca502e77d7db91595ca25c49dbc645afce141bb20d0f15942714b0649f9c876de52039e248384a65acfd44081a82c7129a1102cfa47f3254a0a51b3486826382f6b5c12f7a96cb3b40c917fb77c9da5eb734ac0a862bc914b6e558055ce9d947b66d04867e1168f741b02380315c08e54d637e0f3b01e8071704db49b9e751dbc52c47452b9d96c9ba806333be840af94b550d5e51eaef28176b46b1da730f8e770c134b0428fa5a292db5e857f6a5dd26f76b596c824671f29e14582532e5e8b8f4712403f545f8e1b8728f506ca9aaa4f938b475b4e613824fd29fdf8f53ee8a687c30356951aa8251c43bf217c8b0188556eff35553ae4a13d56921dd037cc9f5c02a33d11442bf22c463d99d98e10ad45857b58198981341289643f8da0cf3c3e42dea376929f81c33c179464ffe69409a6e819410f53aadd778a80bcf197d6ec58db20d36c115a06c138557f52a0f75cfdc13f4dcf4e615340ec3063b0a5ea13eb3b45135ed4c92e475a7e2cc6eeca5904b08aa9bcaddb2e34523dfe8b0d3ed500bb0a984ad22c0dcaa0099a3ef21c61ea3d588f0c42c2354490630d963b8603e03e975996554f1fe71963f2789094a0e189f13f80ef488eb3c46aa232da87501a2300753511a5b15c1211fc1430f317be8f5b2c5e626895bffc4f012e15cd4932c3e4a93e5d5a918915018b28680857050fb443c51ba28ab80f81e84d4bf42a336ea21a0453134fbafafd21660cc197999582b058bc90326931d5baa9c3644ebcf99fcebd94515bd9f24da3e9ec095f54c7a4f9d5834ca789235031dc393b6927da06575921d7dc43a8173ab78d5fc3ecbcb1dcabb10e93821c86c2413fcadafa8e9016cd750299a15590deeab84fd75073cc219a4cfd7eb44a703cdfa5dc7561c06009cc3ea2ff34923a66324602bb25524ab6fabcf2438566292dbe20da7700e87884722adca5c1eaa23ecc7b485c2434c59e9dc0abd3e4de5163884595ee73a455ea1c52d33edd848552e11ef2190d7ae6bf59cf82aa78e97e83f8dd26bfda65f876a24ce5cbbd150c6c4681c3f34bcf33217489818e085aee8aeb2f755e46e5e2fc0efa37205ae0dee1a3f3059100093fff6d26070ab4c0ff45239b9c6774c5a79630bf04fb60f39d912c14cb3fc77abded3f91e9b281df0daca8a6a50e733762ac9ddf05ec2fc738f79bbcafd7afd2f637a8dfd3e060cc361c8292499a5057c368bec8a666be49505e463206f0927d671e8c7d9efae3b2dfdbd344915acfde4efa107d90ab12eabe7fa14ea2d22eb900ecb5d50e24052c6d22fc5fd69daca2ed39fdd9475a9b287d5f655c6efa5600a7a2c3d7212a4527bd73da440efdc3e2b4f0b8129880356c843317ca76c460640272103ec15fdc1d3180e340c20c21a8d65ba158816175dea2d696f3a3911ae91c72bbffe501c036e8ab17747b3127b08797734cd28e28f420d37cd5f55993d95cb3a6e37521eb20e76997bc57399cbd2f0d3a4fcbf991a9424512fc3735153a179ce9f773ba74fc2f12bf18987089e3be22aa04edece367ea2db34853d58fb9821eb3d4c879161002de461744e6a5ac70d1fdccbed48557b61699db6a729ef944e5080e737da0e93b0cb6d9cc0a419a1e71d5f7bddd4b5363ba2103081fa3a94938e1420c47d4d6c59440640028dc13c59b9b451a70eb35c410da6e6d0bea900700173f2799922ee372739076f54da58336727b06dd856cb4aadace3e45293c577743149cbe08f6c4f5338fd5e98d78e922962c3cf340e4d70e305869e9bb3eb5b180db5581bcf3ad561c8d9486927bace386d621bfd8039dc2f70b69f8279e4c997a7fc3c8441e4dc953cbc63eaf515031db87036ee675c01486df1879451e3904cad2cb5248bd549d8520e9601e28dc05e77b58ee963bc5a6e448fe079db1e16cc5cc97bd642f05fd7a26bce8c7b0bb51fe021e466151ceb99bf7190e306332684ea3bb11ac197f9964e09fe9761b2139fd13ede62181a6e01283ce9b68357aeca3c441bf44e81b115abd712f1e1cb4665ad84297caf165f2e1b2c5ee79810eed5f98c51024a605ecc2033d99f44b2a135e7f82a6faf5f14dc3bf6945bac529335af43c3b4462efda7dc680124e9ed4506ea7cbe81ddfb13d9f122041411e87126caec48152bcc1d007b70735a35f5b652330fdd35c2047ac432839e526372fdbe314527f5b642e2540f32c933edaca8e6d052253fd539f54379e9be691cb6846455bedd270dc095829b79492924b9ed49de6974a653177bde0a086fdf32e13509bfc76fef02e81dac59534508b2e80349c345dac0bc5e9ecb04ce7b65b6c883068db554b0ec6a58b672801f2462ac6ce05aaa74e668fa4ea395ac1409bd06345b5d24cd692d4364035055f449816ecd2a95e73f30a31c8ff33a857b5beb490e45f63f00f141c60ae82648f3567322e56c2fd8110e746f203cd6946d62a72b6beb4c60e591899ee41d97d38d02552d2c2e6ffb9ce00f1a3388be49ca70a2ccace9e524cb1e7ab56790dc0374159fa04bdbaa8a8fb2c1221523eb2759e18dcfcda28f0f86a832d4b0a04ebe194f819bc829950d0dc2a257304387cefc143cb1163c44a943ec3d8f0a1123841c061ce57b603a88a0364d02ac499e409c08890802c4c3c3723fdb20f7ec1f622069e7e96e979e0d12a1eff9c7ed396def37daf7e37ec907354dc00e820b776e7e65d1d1e561dc856f8e94fa52454ea001d2d427e3f62854dc3da1f3f0ae17200ce242c58fdbf8c7877f6edf72b26da44aea71a8a6eec5461679b1a1a2d8a220ea48819e9b0db43e98b6fdcb07f61a840705729896788183f50979d1a90abad35e329030ad28564e221748cdc5cb1c837fb88c22351258b1047c2571db2234a2f4e73111682bc4cb49dc4d082acfa952b5cca7731c6de51a3c4b40930cfe8dc7f4f67b43093d70f4a5b38e252bbdab882a14cf02f9c700def4927a6687c7f8dacd847bb067f79160ffcf05774d16905f531a28cec3354cac3dd5dd50e5daf6559dca9ff2b5245272dfebac1595a0dc051c56e372d805eaea880759c7b72a9791fb64c8584a81807f16fa6c043f4b69dfb1e087390720e3ef4ffec71483329d7c20e5458db8484ed9b34b1438192d91eb5e6c5f44df80433bfab089da45dd17a0f074c6157df10d214dce09c9b74ef1e8e782b4689ae6e8563def626d2a8bc5a570b628a0ed9d5b2b735840277de8f200cd42fd1f26a1cba47dcc638f40849247e1db704576a387b5c52bb6396d0ecbe01ff85b2d0804dc6eda844c7a69a6a9cc616c8712aa139bef4906e05b26aba8532c254baf6b2eee1d2a9618fde7190bce7389c1e8dba5a9859659e601869b1d4eb3c53aecbcd5e096a34ed97fb04893c048da9ba2f82d7662465a3cb8757c48268cd432e0a934856403146a92c1c7a0c9c0187eb66dce0b13444a29a28f6a3eea51ae97070d2f5bb19e6b01485b9e724f9cbdee6431a2396abbc787915debd6b696176d390b17d609d5b197e8735d614efd3f81159deb1b80d754a684cd8f49a818701825c1a3bee13b2c4a0491c9f60f69014a308fd82935000f94704274aab02e86201d3df05bb0afd9aa4c3245057626a2157be073fafbf770072a16068e66193afcc47daafcbf029ac6320e8c571a7d5ef9c0b02570c974cb7380a8f211a725ab5909c5f253ad0f74d5745919cb05493c2ebe6976671ec58e33bf0f7da5266c1f1547695466ba868d21ff9801b7e0102019511e95df000b1c3780842343f523cfb91f6c667e9b5ec1dc6a27b2a260d213f66974a32af63e25280a6812a100ce66a4852d620228fcaebb858e66aa03617a2a572d61d7821d674fca361760269ec28181d34155aed4384623cb218dfbebd8060aee23dab42121fbefb31eabd5651ecf5a47dba0b101eb23f2cbb74c4ee059884978a4c920f52e37d6f255d5268d017ad61e8045072e5afe61275a6f5092d57257c0da8dd23fcab7b04508482cf8df55e76baa711029306d88c188d9ee584853de9d28792e78d78f4a320bead26616b00b8dbc67de2d5a3e1a56225030fe79e2e9e33e593a45602d5a617b2e6144885838cb516b69605b8d939f57e5e99aead830a13594435577d28d9d3bab18955b85b5e8c4972e834f9210faec58be70aacb10062c348e2239b72be886fec1cfa0fc5e5995145654dd44a50d65ff4ca485c0261fa1149b386b4180e8cbaf96a7edfba1ed241c8b86b3e561fe1db0ef4ff52c524b8a8dd279d12fd9447ffdc5a55cc1717d0ab07eb1b66289e21094d31690b9e99abf5cb56a1158a306f55396342f28ece254e07fcb2d73f83379f0b87bcfb7cd888b34438297179cf40045aee6dac031dbb1185ae979e19f555a087ffad87c1ae8d9487f1b83ed2871f7cd071b7ed03361b81028e95742ff189df11870da6bcd9bd7d223ff8a17ec66b7ea46580768c60c808d2e96c1853954b0f964885c62ad20fbb3796c3b975ed396f313bdd16828f13010f29ad226ebb7bc188d0d25f7a9357ab97c70cfcc056213456d1ad6ea10e6a38530994161747ada01f26f46d030d0832cd94b2deefa0a3c635cf51650d9822bcba9cbbb4af874358724374976b2d239a8ef7ba29508404719a20b44ebdb665a31c78ef4b35e7935039d4e28eb433d1ab903d437164085d361c6f7222f99a85e02ac343aa891df6a79c3495e98e50c1e6df50b7f7f71cf2deffea3c8c8a312e6a40aec5d7d0011a7ec39b6b161aefe1fda6d947a427efb6ab3da63389d49354cc02498cb9fb37fae077ab13369c0ca99b1a191334c4d40e061cd84b755d16bee5152d42169cb13a332ac291bfe995dd59bf4aa37ce4f723c3ebf8cc9ec7cc49494f90c452e9824702317a364092c30fd7a31bbaa558f7ea92d0a8e691e0588887961a87bb7a80cb67643c33f2edbb6f4172184a9163f75f80476ac810e70ed908a4a4725f187d9b42ee73940c15546262b0e7445413a7a616509d9dc2853cca695fd1c647b80883272b31b487d46d4f6dc2b2f00d49ca02d762400dd8848cb555be9c04ec5f3058a36c3285196ccf28afeefc643eb4811cab11134849601457b3e19d2a7a445914dfe0c8f4617d0f649e1f343043e259c90ac2ca24e1dccf172c4a2818c8b7ec5ea8d173afd244590e8c8d5d5c5c8a64ad3cf2997b33d519c3949ff8cc5dfe55394ac560ce55ee1e045f04c467f1e4e5522dd30cecde9fd0cc1e66701a736be7f28a7b15d68bae80eff9a360ad3a669568edadd55960b36c7255437260f508b4c37b25dc742aa25af647b909bb732b1b73859e4378e7b07d3f54d381622c3d03a962636f491f5652b911e0f2363141f6bd9e5bf02af6807399843c34284da59e2ac0cb20ff7d7b4d9d662b8072e9b6f4b40aa1e882c3b0f191860c1ac2a0f30d430f4f6f615f62f27aaaeaeba0b34a1233c559e0817b053b7c50782f93eaf46cece014169daaa1b8c81287bbdc5c05e43e9ec39d399a78733f842e3b1995cd525c42d08dd03c51a0680226f2f84fccef4116f8dd41472d0b35561f42720e5a9b9a4def3ec0482f1c55e311c6620f9030f237f4826485e05bdbef561715df50e8664923a2fc03f295d15404c4c7b009760829bec6631f1660a13510f792806aa961c2ca13a22d074b4ba39d90d05b3c10f8f5374173c3d5ec63fef2bb3e39ca0e1aadb17273fc511d7f7ca8f58972b90c946e30d908e46e7acfbf1616a59c04195b107769850fed4c3354055b2067366c925c84d8ca3aff0f4639209b0b24d726a72ba0d531e900f687d26800a685e37a4493e2ad45680901b683a28e095b825a87095628ab8817d7d3b70ed93f1959280825e06529b5400cc3b28de6949bf824e2e32ac564c13cb76146748c45d6010cb9ad3c5ff109ec75b970c6a1d9066743596334c033c12413021298176b688a6d1cf3d4bd12592f16a4367df663188a74b130290d245dd21192f822115522a06c140b76c6f58f67805ffd9651c1b50ed35c0d1264c5d70b0318f85686a6fa0663c492ad500e4f6ba84e75088fcabf171398311caf21bfb6aa10f760f501b3a77497d63506e90fa77a38ffd5565f8721fa9f43f5668d014af9ab1edddfe30c3e19ec36ca9ac4860b016b49bc9ed58749853badaaf1197874ee1a9b409b77ea9e450f1901922b1e06967680617143c467ba4388f1d3dfc54027df90e8be63d30c250c0ccdffb8ab1ef281a1097b306f3f1c5e873d175d4d35d059e31d73e86c85dc7a9adca9b9615ecbb5c9f64e2d9ae9cd0d80171f66d5cc84d10734ee8081c088e7a84aa4fc520d8470fd61bf230f2533a7360a63f80b5f4a338ba455d9aaa8e9766e2c3a13a0fd66caf2fb212339f1d6c4ba17b9ee1e9b6c39738dc13641a2213be73f527124012c10cdf7b5bfe95f2177a29228ab08370b761be053aaf5154814c442f3554e983bd3764b49ad3129e51c0dbc9885aca83501785717aed6c4be1154dc555ca53b9764b81da08245c9dad426ecb3ac479a7db229fc23b87b49e90293c3f2d5fee2843bf0dcde6e7717763ca9c3aa1da05eadd41e6df8c1fc45438a518b433dec6e0efab359943a78398464d6973a757fcb07dcffa51d432cd702006f3d0d4861d99b4d1ea32a6645022df5d24a5db5389a99bace9242204998001b9efbc9f2f50042dba8050a94658cb2279d0adbe2b21bd619087889cba6103ad970abf8e83b7671222d6b29012c2a31262c18f04ce498224785200749a0989ffe4357b0b167fec4c97ebd037fe1a48d34124c014d751b339bcbb85563241b0fa53197cce525f041f374db19737e2128585fc08fb2c873ce61516380931b6cd4fc085ee3f7e2fdac1d1e0cafcd81c07b17b8b610a06c5308875521dd34a7d58be1fd294705735baa4c6a989f044eb033b02910917a7763b9bb02c164afc544c1ffdb3a4807d92dddb54312105fd4d1b885f15b9421a6812476c0776590123004e12462cef412eb8466b50bdc7a0c8104aedc039b2926070afc77f3a4d0bef9578728df5ac936620415104776351c99967806d27485f3cabe4f73f338e19395081e1918cd5221899b7262f7bd36bb82c89c57c43a0248a81ebed859b559613a066e34c90fe3c44335306ec03ba48c047be4e80a08e70a4acf3f1b7e2036478de78c4ff78f05dbd3965ac70c83ea807ac09d8e60d2fd03d7b5074256042d138e66624ae64ae60214172512a7e07d3f7877a0375423bc9ace51c07475496debb328436551d2799b63706f38382db60831cb5e8f85b7ff61e06ac7e2b35fc03eca24d80d64f9949c1be6feefcb5ad22d80269e8380008b04c1106079607b0037652da8e2bb6f8a60f94a89a36639ffcd81b2ebd17eea9a560bfd7493ebb278cf61e8a589f6467209224a96c3f023b0afddea1ad700329530568a3d85ed89e7ea52c84693241d9813ee4bbeed16f310e4a3829961511c08209f917a2a4abe337c31bb1d83d13d3bb4cf346d511f424223ab4c0c08c07ca11418a810d04fe55ce0813aa3304e9dab1725906205d7967f155b2c30a12e17dc47276431d3d7a778a78afb29cf109054a85d39459e2c6c759108787c67a3adc5c74cd55b68101939f1218e0597543eb055c7de358349966e490fdd548d43d3ca33ae9a396f5f3556f11d3a4535509336420deb8072373e4c65c22aed31b28bd9157382b40e27697c80b31c7a405c179855e0c733d346b01144469c13bc21c58d688509c24e044704d8b8ab3920284bcf28c8063d4c8f28eb47aa7404165f76c35498fd35e2383fcb9c46a968a64abdeb8a7816f78e22135d03eb1c208f017ad7ff2ef6afba19d9ed01154180ab550bdd0aa444e774093fabdfb972e0f590e268fb8d0287145c55baa281089f28f2064311c973659a82e234bf2b9ac671aa485747e968e99b4ffe4268864a572390deda52b55009024f387a2ec6032078729a29718851b404ff48fd0c15c190612660d5d9b9bb11d0849a0c1acf8b951c2f22cb8ee9705a0261e5dbf70015d1b9c533a581f0bae600201605f6425145b24d0cf5cb4c8061f804205e5c1b02466e25a4294286f814f285dd8dd0c048603eb7401440e3f7686a62ab8a7e55ac0a9cf3f1c6d21c074aa63712b62679d4bb8d15c7af2dce05984781c1115f9944b06538d1d0d6b0e60b110f7a0bec59fd8277148bef374c3d65364f494f5f6c947222f416928216c8132a1884dfd20967a245d55a4e4148f1734f586ff2f80f3674e6285f70274c97b538625fc6b69ecfbb6118c782dedb846f86550f5e9719fd6853ee6bf797b8d4f879fb84858fe1fe09e2ffc788f6abcbf46576143ba6b687e93c14dcb7e55d2d9ecb9084811355e84ac7603e365e63a9c941054f94186ec74b758636f159fbceca6a53b43aa7bc2a80abf044eaf2bef781483a1040c46fd0db08d0832c7a0b9bde6718dec55022ca6e582852c60434725049999f245b9f5fe9693cec6d5e45170fbd732326850808f37772c0ac8b3c587fc9c96e4dd81e424192050eb7c7c2b1ae0ced1c1214e84be61b9b00f3ab92fae4eca9fee03bf676d58ed53f32f414dc605eaf184def775bad0c30b3f234aaee3399f05a6bdda907816287c7e6dfdb2e231cc9adcb97226dad0e6e197310985a473c0ed471bc5a9e7ea5dc013243d1306d0031a87aa60a5b8f6454f5848377fa8cc15fa9014ff623f2215bba7204df507f1774349b33639623eabb3a9a4a2f4926b68a2323b26670a7b87c7f04eeee3f42e765d6fcaac963aa91bac74505f154311b0483404633ef1a5905ec4714d359e5a8687eb1f7da150f5f7da0b872a75df542993fa12a49c23448d02d6fedd32158f7661e3dbaf1b8d3a7bacf67522efbeb23895f530ecb8a0c30ac1166919b93537bf469cc70462572c7d6a07d283dc50865201cbc63837c901d87aa98a1317cbcf798097100c1ca6b908c495af0cb93c42620132965179c9d0189f0ca6897d50bb0550c541a3112251800e3e55d91ebdbb3363e13cb9b77d59e4e46896a4d7e1dba4d0c06502a47ae38cd50c8e0a0f2e9b54f864ae1c59e5a69262a6e6992bdbb1c0023ea19e82414c104b58e6cfe7d21bc4dc49dffa1c35fc6726f30903af0cada0c63e4330290063de42c27c37c5b77e7f53f0a060f946e785b2d4e2c934f452436620cbdbd7e6cacdfef1691d13fdab6de591d0d91fc05cf9e7e2d861738af1874c3085812e736c427c1c50bfc397b22476dda2486a302793866a51a319edbe946625a672b12ebcea6a2d114a3c5c6131deba95378b02a0288b944f30e2793958f7efd4428d77e3cc4f0893c24530ae76b78f9fb4ee769eb4449327e78e5d2d199ac1fdaf326d0e6151427e1ae4ccbd3743adddc351b11c26c333c94c75d9863aa50cab16dea7ff8548d485de97db0bdf8ef65bfa7b2b85b0c8d646ae52029cb7470223f78529293d6a1143835ddf81bb8708a30c839a48d017c58480bca1759bd12e88ca615c114b483001efce5efd6505db901a615d94045fe9138627c00a1e6449bf486c9aa477407d0b037770751d47ad8e310ec3349c3839fcb4f9cfd266fcfb239af51cde1d6d63a86a70087127e8041e63f713626124ad003a7d7df5c868fe18362e27f6a060346d70876860e7c49c3570896ebc4557129baa765d7f729eff93751d88030d82384d112725688fbe36043959c6b4264c603aa2888c06352af27d23ac1e43b2b316e8285bf31c556adf313e24c116550faa907dd26c8dad094d8a84c72dc6354dd192c2492df285d60554690080d7451446a488154ded0de46023f2e5486d5e0fe2dea202a6de08e262538301741121797042137340d5dbf10c599751cdbd29976eac1ef721d2d378d353ae05d41703a4fb9edcc45037697199983433f1dc445c6e038ee1d3936932ddd0aac411c7bb5b89c35a018f913430971efa546c0aa4c5ee23a030b65fc304d46e4a0aeba9e700c4219c7097786f2f837ada98859d9c87d9f571644386f61ba21ab4e056a371a90217d5649d3a2320e4a4241dadb1deea69aa06ad6e92bf550012204543f307b519352a03405421a4a7e23613499e0338134ba637afd9a634851abda9b412490df80ced8fdb5d1c840d6fcf973b1c7ce012bf08afc04f4001a6100dc2fb9cac0cbda27d2de63c1fb6ea4a5e930084d3f5b0a47f25a97e0d45d647ffe077c4701aa09500d8fd19d449cc7f248487b4ec096b11adfc2445ed7eeddaf5807eb2a9093ad996020842f6db1779292cb2aab59a3bafd5c4fd9110ca5a84df39cd88d7ff31728f74999a976d73f5ef10fb403655187e202efbb67c7adca752c8a64a52a2dece450a784c119a1d3db884270a6573c97cec4156a22420e8c985449171662a2bd859137de1c28911c45b0f2c67940f31de8b6a536419a8070ba4b3f411a7bab3952f24e90c329b71e8caf83940d72b87ae82016c392b9721b00e932cf706e1aa47f90d89a41821d0bf826753bbb65b7a4683adaae0fc9f4daceb99c8d456c3ae6a894d4096a1c5e9114dd063991583861f33865dd1af11172c6f4691fa277ea59462c620343dbfff5bdfa3fef2bd13d0338a729d9a8146fde85ce6d116b804c05d452c446264724d8b0b3f5056212aaafeb7ab216f8e569d4264992ba3acafbf53ac41b9c88d403c69853fb1801ad7519c38b3f4fc80b9a3ff381a67183a101b7c1fcd0d66ba308d357d41f3f1e234f7e94b10a07be5614cf6a7e132274d043cbdb25d0148d12ec6642d20bf935723ee35e6970cb98870c16cfd86bddeffe641a1ae7ab6142365ac2f601b533f283281868421edb592b5401a60778aa88003d5990c5d4d7d382a9bf3ac1413d28b5ca5329c21126a38353fd8bbdf3fccb7799ad996eb082489307e6ebdb6128604473da99b5f2dec0871b7add434540af2f1b7de878d064807448d00961528948a2d56ece01d452bec1e414182687009a96c82dd562ff7cbbac69ab817a5bd905cf73e9c33fa5337bdf2973df2133dc93b3fc99f7ae9938e2f27f07bba2746871bba0326caa408847d6df9105ddb6c8e6a9ee4219e914b460354c4af5aba4b559040d227f0cb47236e6205f7e2698f03405b77039a9adfb49b777d71b85294216c84bfc17f65093e7ffa276044bbe13d50593271aa087515ea605aa624fe0f724a6e5e000f06f2a45eba271f92f95fcc3b21d10375f906c4040bdbe0fb2e51dc85f283673582b41423c5d4e069d747e73c3e26a548380fcd2601cd0bd580be5d1e7b601565eb9f8fc1510574793ed9d698be4ba1f51269aacdfd1903f3f012fd09710e464c005bc671bbb7582224aa1813acf61ca9ee84bfae6fe80483002e04c8a116f3926b7f2b53fd553e2c4cab197cd132e97303b89eb33df33b507de56ce9cb97774843c33eb883b50a7bb5311da4e629ccf3bdba1a51186ec20e8ded992d4b4a7809e287bedd8c825cdbb7dc0b8c8e0b95589be30db7cbdb070a8f1455d0eb9cbc98a1692da76e408ea70c006d60695dd25e545cd0a9ab7cf1de7fff4fc316964241486638ad738d907cedacb1eba61a8b1c6c484c50bf6aee27bb6e393e7f311bb1b15a8bd64537cc1649655bd1532a971d7b2ac4d4bf774562815ca7c124a6638e5ce8665d7c88af02cd6e8de91f28734d7c0dea78aa0e6c62789fe1fb678d4a82f6ecbab14b56ef6888747be6af06bd19c78a5012c603c80e76a6d12afe20f735995451f4128bdba1052d1de00296a2922492aaa6579a2573be14e1b654ff79ac42194e5b44c1d84e832430c625924b218fa3dd7f23b9bc40f58701b4027c3c9b53b3bd9f8934de7deb426e4db8b0a19aeae1348398d2a2a57110941261ee3ca484af804f2b5335caa964ffa632abb4c9907ab620cc13165753d1066f37d432d0679f3c775347106196d7dd83a86d7a14b86bef0795fd183330cb067981ec1e1fd3cbd4b9a183c57ca303313bdae0014ee1c0993c240b726e3f737fdb44f6c2ea8bf57ce6c8b0fd93b20ab33eb6ad558c49d424ea0674dadea110d03269bc56097a747e06aac98d923314e574a14ac82f10c5161798a61365cea86c1b6bc6560c870547da41bc33db5d916accdf551e5b7a4735479801e1d1d14ed20c17a5fb94e22a08d6f644e3954bbfc748c5cbddb01541f3b03424e0e76b901c70f7fcec0896e7dc06ae8fef467a07fc5df17719340408b6c8fefbe53f1fdcc732ea9c7d97b4c15549ed12fc6f967cf2fda1c89b850d76a87eaabd1b822a108fe36b57520ba95c7154f94bb15d7e25aaf5878b5a4e3530e871aa354a2a5a53b47932cec93d61ccaebcc77384f88c4dbc4f07bf02d61be9d6afa04bde4c5a5d913e5ca56a1c4ddb26d2a6a991056fa5ad679fdb87941825b825e478af1c286d5ce24b10edfcb0db0e2dbeccb89200ce824391cb0b0bcab78a8169306a289ba1488466b75468765942b3b321db6b3328975d9b35228383a00d2516002e2e99ad5c4ec4dc5b5ea33cc2867a226bdfde8e0ebd49ffb6933ea7b12777dfcf7a1a328edb2d0b36ab05c006be3a274c38c8733f1f1c0c961510c0e8d49051b98ce07fc420ed8c170ebd17b1530e2a8b55bbdee72ab9754b260a24699df026107cdacbe05c87be52bf45a2e532267ae88aa30f45f872f94c5243772a0543effb8571010b42017da7668d05bdc83252a22d889fc42a01882cb682962934ecbc63ceb8a35535624d6f398882421b67d711c520646f2acdd0fe6ef614b925b262640ba24aca3a99bc42bc3c6851ca154182094805878342c0dd9a1e29f9464e9462c4ebca67af309ec8bdbb73b51be3586e025fb7fb1cbd327454494c3b58cc675b1b537e55cf03e13f8348f61cdb391fd8bb120471c172b852c26d9869f89de892a6605c408d5b22ab2ffe6392fe52d834650b52727a8c30403793b1d8f225634eb4ea7a8aeb96d5f0381089c2f43d6000ea5096a030c68de421627f2536688e11b303db2bfecf18ab96c47f2dec0f140bf93546da08505cc61d6710d35623163050581024db631ef7a07665392c2f60f481945c45e430663217da6d5998881f86fe731fbd493e44e70d96d87cc7529b68200ba88b4017fd2e70c30c29275c839e58b0bb75f6477cf8eb0f5d3dc3ad2330e61abca5fb2d5417c1806a25c83c59a23fd69abf10abfc5bd283925cd226291c4f283b241fc0083ac6df7956760e79d0a19d94409411d991bfb459b9d79ff68c2b8d460d5a5bbe69d2887b0858a5958a2edd4701328fc2a62aedd66ffabb1497ce8a90342212568d1bae65eefaabc072b21321e4846169015e5141b42a2175af58238176b5069ef839781ca8381f0027716f7053e4867d4b52f59cc080be88aee976cf8498edf2c3bd1b5ec09c505ef6599de08259ec95d8e005398a6991ee45ff1868908d5da34e3a05d4a324a43af2d119769735a232f3572e510f28bbf8da762292f7ae4c6f868205c84461783f4ba0a31f45d6dce2b667affbd956c8b4c927b070f1947db13a19cad94b270dc252ed7e9823b05553bf9e3aa11457b78fee1da5b5a1bb91cde80bbe910e95086c5f4746dcdc60c08226620db7431aca4a6b0c3e76b13b8cfb4c545bf7c667f015cd17abfcf0623442abf78868e996f5b101cc01108b25e6bb78ff11c0878833d2340a6025b3d42be2e64125b81eb95cb470e33e0315f40bcee4b9b8d7fe4de50fd3e99467d9d2f8e646ada2faa101478a55a57bc00227eb77b0f718403003b352cfb5b210ef72cfacf277b99a02d3668b80808ab2717998580b384a5dc582e0567de8df06b0bcdc06adbab46687ddf6454220be09b3972396e74b9eb4d85a79c738e83b233739c69cfb7782a8f20cabef22fa831b7cdb2d3f095e34c4226d5d52bf1e279a99d429a758935e3d30e07b9224f0a0c0699c6649288854e51d0513b912f222954f507c2d57b78b5fda1a97970f29f60ce287dc0da3cebcca2e0ae298fa11fffc5012a3eef3773af401336e3c156d05a8091787cbaefc5270a78f5136d2bcea0e1a7610612e663cd35266bbadce3a6698f167f275025b4f42d1c43ccb83a96269c52b6cc717eda988b3ff19218ca19d1e15aa9238937d19d71237cc9b68167b009afc476e64e50c8142cd24eb4b6d393eedc90a3d9aa11642fefd7a79077362baa56c99e3a3aad182c4d35da371893baefe0ed1fd3513d27aa9488520b2ddbe54394695ab186c4b5b32259745951925d83ab9050a07f8a6104d975bea43ae540a0ba3da6fc262eb46006f311eb59c5a41dc19b9f5e835d3b8def587648876cf7284f3d8e7ab3e92a609d136510f93b8db3fccced1a48531e1fa11b689cbbce2175aa5b948618dc146b72980f891fdc0a952824e208f4cf02da5e22c96300e84bd9fb065fee697b9a5200e879e47989f77b49b4e6871914be33e80bdd96bee90fcf74c8644a6be9a444d788f92e4f72e87a3f2c296de4b9fd5c406db91e76143d766825dcb40b355b320b54dd29837d28ecba1b2f47c3a859dcc1e0021ecaf67425f45f254f6ed5634702f355c07530ddcfe5be4ca295eab4e941506f605b99e8d3d054b41551fae7e214dad3fd818541cab499843edf772175e531aa892fb7203fba757601898ee2c88553315532947f33ad3827272da84a8fe40dce1802d9f9f3d37383f41636fa3650b1e09d55a9808a3e5d4b7b8d1c9ef108ec2cef8c8a0a8f04ad55000441626b96330438bd2b2dddab03e84c7924d5a77a877ec0f86bd735ffb8598caeae4a2aac0c7b565f9b193abc7a0a4435658d3f665ac14068d31a828e89d5621ec0f132f5c82970c1fa8f33c436280e91047523cc3e440525b123b3bace98f53030c2c4131aa1233e78b1a2ad033d424d476bdcf698fc9e5e8f25f7836704eb9b9467cd04396d500ce20885358e5999fe07b0b84ca565c926eaa2acb85eeddd28d8fe742b661bfa8960966aa030a104fe644df3a1f94e735ca6ad8be9a678c944ff5cf8dabc4e042e4bf4cca5e32ea2187c98f02f57a97f61d313b48ef1f9290ec7db29c11f2f4ebb7623fd33a6d4f62c73994100cdf4c7df4600abad663eb0b761f52cdc5e87c0ce3c6c336d5c7a25d8be0049e161422195f7f94810335947adaaccebfdc3de530a6d23ded1b3a01188ebf673c717912480d494b230f17a96df30f7df7244caac231b7661567cf2d4b6b98f81eb6b8f66a7eac30a47a701e6cbe48b194174af09d884dafb2e7b044255392252cb697ee847630cab7c308a91d0627151562ef6a8d2255032d7e21c6b5b8aa32b1d4543737d69d9afbf6a8385e35848d7149a6331a5c7d023af3e857d3b676bed4998c3ca1600efc72280197616c71e80ab9bc7f917fb264259d4ddaa159f01f6c712519172c5ac29b2a24fcb0585a697844fcd2093ef789e1547091f2075dbc69fd961ee787bfa0a45969b8391bd6c4874476fb9d8524bdcd04ead886f6c605ec04abefc46726c553bf6ce429938104a70ca5bcc2900ac5f7ca28f2679d21129961899fce656e613812a363d41dec517bdca4ffdf9024074774058273dba9fa1baabb44a83bf7f2694e6732bb5d2505c9c9e1c540a287db69bb30f025120942d0a3352287be7d4b2c3e1424338a86fdf465afb312308422fac1cf6d0cdae911a83c87a04ad28fda4c90278d19c0a2eaaba1645b1b679968340a84f2ff839235b40646aa59df7823d8521b56e4d2e52b5037b2b498e8ff39407e44df3e0783457307378e18aa8ab9e5111de5f12c5e70c64691494a5875b1fa36c3507db8509c085b0ce58b91a23494c7ff211c83473428066bca552fa4a407258ebe5dfd3b3c30322831bb6f64bee50937cf1394d58332cb41de6aa53f7fda7a89b66fe6ad0f17908f53211a7f647ba0131f4bfdeaba76cffef727c712aac9d4eeb40c7cf684a013b05c87d738c5c3c564665a1e47d01d50e0b5532b9442246a792caa07a7fbf82ef9eac24ee39f4d2ffa235d2bf75a1500b9229808116b8d11b6d40ce8bb67e82058b9eac197793d398c171ff9587058f1bba33f218e35c43b3ed5819321ac788f4bf8da326741b803eb9a4c937d2700996072f6df83db063ee0f5c9bb271c930b1cad1e8a621c2854b9061a0d8385f28605018f5b99934af9208d547d67afab081b534c3da1d3592b87b0cbf3abfe15e9d87fe3ebf287646614f9451d1baed977f9b8e3d7bec28c6a08fd7cd5759e4307455f1caedfb5c9d2e4edcc93d3f59ca803551b455eb344d69b39e064a2fb202673320cf40c4b145a8d5c0fbe142b067503e8d54fb792d7f983a0775db9685903f55d55e1eb9e9ee9a5b084d42db299477132f3077d5383f48684f60f9e40aee7e57aa32321164dac666b50764a055c9d5ab69f95ffed412c517ef6c09bc6903c4d69400b5c0ffa0c7bfab02b68a4aecc7f291b430320001af4b196590dd0144ec8d7e6ddd2d67740bf7fcbc83f8f1853a4722adc45c06905ce0105a52afa95d49d360797f9e33ea386a8246b261b16f942517ed0fbf1885c6a58b4be078cfd091807ced212970f22767b79a4f0883022fa79c7d139a993405d19bfd9634879b714e09f6c3154fba306fa3b2830a138f1bca3af418f2ae0e3bbabe99bf03e48263236aa842e8c788470731222276de58096785ce6fce38ee2387d38a562fbd30e944b8a5d86314d5b019c04d5b54c8593b92217266fc4b1aa6e0d5041425d038b2a23a78a779f1ff1a0e445f2f23e740292c0ee3f21953ab3c81a64187f24b5c49c49ca3b976003096b5e5ae0bf8630744add40323f6e96ebbed25016d06d6d305af9511c044ab79310ba9b080f87080feed0fc3e4458ea5056954e53aa3831c0a15ebc8aec0df30eb6a539567bfb43c47ab9c13bd60e521994cc27ed79112be1eea680235250a27c20c8de6609ee53842533c525a2982ce6a0fd5006df4b228cc9af84a09cc199c8d8db21b8b478f1608fd032c826d875d4a0239ce63ff6aeb314d0b2870761d31876078000059705c856ad136fca391e488302298702006c439498c9220cf8069237359507d8923a6395b88fa82a95d82076271fe58006792c0259cc933fb8c8273dcbf08d51a48cb0f9219fc9ad34f7e398e5cfcb46dc739680a9e806f79057e5132506a0322dacb413c8de673b1b594556afdb319afc50a70361ed5830fdb7cf3f1194c3775d9b835c22e43382e4f2440786700153b510e0abb83aed1cf0f9adce94e07e00321fbf63c0ebb8a169f5006562633820d0c7dd7b17225bacc44a3e58b3f2d015e5fc478524a0a718986519d28276604dd731471c9b153da407472a4b4b3b67131401513de94f365f65a64751cd080523c4712298247df8a8b1ecd74128cd57536b33178213f0d2c3e50aecc1822eda6cccf7a44f5ec40762dea894219e465aa725e3b266a30a0c67b1ef4188d2242cf238e24653a89645a7ceab23018958c3bf35ddd3ae6986ba552e24c950c315f879c6eae4157d7526f0ce6c6d97364392e9d8b630060eb6b7a7cdca51751bdf8195368465e47d9e417cef3c47fae9a07da749b98350e0e76723d6b4a478cbc6111465003d3367e21093cf7e86c65ed3ca3375794d086fbc1f58c2835ce52c0444170bdd2aff1a2b2fcbcc14136e2d859b95ede4612bd588548e491b127ea2e01ad15e3ab2bb2de92f54e45af3904af0fd476576b9b6d78e4a1b086b6c6b9a343cf117257ba1b550a0bf8056ddeb626889fa375e40cc11f4cc94dbfe8df1aed71daaf18f7cd1e9166cfaefc3fe61b440b5813fa40f59f0f37e1f80f3d3ee552bcc1aae752454cc0e3ebb2dd48ea1f4671556e489585899602759c5f25ebafd7d28f4406f561e0fd720778439d10a211c2b85ae8a95fba3c33b29a252dce46e26cbfc1d8a09135945b2d2a8a0bcce303b8309263906ebdb7ebbdeef34d6ee7365190fe32bc47dc258ea006fc7086044a3017ed7ceadb0be2796bfe57c3a3ccd1960bc229a325515a7c4642081b7b4ff7dc194ab7d0bbc3981c3689b7e322e00bcd1d785c03f49a7e6fdb5680ccda8b230733fcecfe4f841e3963f3f57196613a9069e30bd8cd2f8d770e57f0a630346c7ca7258562d705d1e9c61db43f398135ed363fe1b0b9f6a5ba27181f87ecc1ab133879dd9491262d9aa330bc43a95d9948bfcba2acd45374e0c44e2edaf1597531b523034e447d9812d27233806ac61cc507c628846b6d6217ad82259c5b18084ba3bb6f27fa9785cbd496fbcc5bc3fa3af9390cad105a9d3ca0a27bb70ab4f61712a7cb41ddc371e23994685e20505e6cb1c00537eb962a0b145a565f3b40926dbdb425bdb36810f30a9bb9b07a7c483e2ee39367bbd109738a77bce70ec9e8c70cbaab860be02326328af1ef92667666924b31087c9769f54017fdd964e3e1b6548c413d6f1094106c7859540bdcf09809dc49acc90a908ebd1fa10918ef04be6a7eb6387893158fa5fad557278f60e4283fca0d0a7c38735814d2eb0dee020a11b8ad5cc1768cbbaf233b5ceb52ea2b4847ab4fb7ded73fc170088631b3ce0bf76b0c8a66a64fb55c40204c73d576132556a804ae077971f148d079098dde4eec0ab9132128e52407c4286f6783f43ee7a3f042c672f82059faa2ac8aa6ff345de3d6585eecc6a11472bc2339947440fa7f4831d71f8498293dd82e1c218f5fff4da2750405fa38ac301c385aabecb886cfeff1fd9c068fee521bcb2d5bf0b580111eaa9152b3bbcdf0ce437ae47715ee3026935cad34bff9c59f55ef3f9bfa69cd71d21361d76524922bbe559c246263ad6eb717ef363feb25070a71a537f8cbc75d19c7a525ca3b86a765d894a69fca2a4e52304babc3874ee9594c8bdd56480682eb42f2d5b21515236b4c9336456133f6fc625e99a8fb4b85ddee56a09844121f5470d37367379186130290d7f824a508e8873753c6a4916bed61f428c77cdb30390b86625ae4cf9ab289b29e4bda06ee57da81ab9f92e96eb3496f11005b51f6adfe2fb2426a60d8d97d6ad94ce075693c59d5a182d0a60f58e0570d066e7fac5da30b27d7f8cd608c93c013fe5daf6ab6947eee674ea5370c3eb25d4caef2452e4bee9e46a55232fa54ee12d7105735768ba3e4dfe6f550061bb7bcf83a5c3afbb350d17f8038c9ae3da04b1b28054c723ebc2199d64593b7ceb88dc9d6bfeead47c6a277eda76e064d8977eb4751d1b94bed39393363796873620fc07b29de2dca4ae45aceaafbf6de3d570415531c43caed48ee233c1c9615487475caa18843466dca0043441ecf8215ec331b6bc7af98d67d46ce1e5108055e713153dcb47cc2f58d8cc64023ec3e8565ca883d76cefa77b74a52c2ef115c2a73c431412a7821c6f2412e8cf618a78fcbf1568d52d580778e2861b46991d4e8db903d751edd9692ba12395945c1431ba01b05b002c113b1825d131fcb164102a6b9747276474e3623171a6d6e81876006941dff4047687184f1d51d40276d67e9b89e3fb88d666139235408a296878279115d989e71f17b503230d95fc908547fcbfbe80672899432d9f73ca1feabe5aa691820a33253f4ec82810d99feb22bc4ab6313d11bb057f9de618012e33d261e1a8ada9b20ddcd790380252c4fb2b8850d50111047445da18c60f1d2a55323e6358255bea608753943954cf818f6ab0c06325e9157f12f8b9f0a126dff29928f59c593e149d01f5452c551a2da319ba54a2cbae0d6acc5994c8b6c685366f941c4ab101085b3fcc84ba0fe9331a1016aee65310184342f208affdb27743410d7a35382d2d1182ce007bf17a05d03f8e46f10a342fa8575aba8a8c771ae4c3338c75cadf71b12bf92147c3a7f321ad491f50581a8911ea66e381a9014294e238ecf9ea183e68f84b55e092bc6e810790e2cdc05b3879cf7767db58cfd1dec6785f268a1288d68381242d6ad999f341069023f8db9251e825a920475bf777b050ecedf152c5d0166f550c6df15685d1164fd5186df1548d911d4f9518dbf15489b11d5e9518ba89d16c2aa054686b025ee0293714b01d1e7d9ca053036935d79ac343cadc894e5f0843d5f4dcdeca435b6512a2838c3ccf8c015920c35106cccbca01f036bf703f1242eeafc6776a7f2f6feb1b6afbd84fa9e07b0304e90c12bc1c8705e3711a5d79298ec091b4b4466d99e90643a96ac65305041d8854a5dc68f77e5e0ef6793492f8af77336924fabbcddfb5745db5969e4fb98a4fa3a5f66f2141f5f7a6449b0f585cf9be119de43fce4a6d41a97c51ed480e860175c7400bcb3092d988a2416672e08999e31f4f4f902788265184447ba69e9583f19bdcfc8977eea06f54237f6ccdfcee4935809fd4e022cbbb5f59f159ac300434949526e73ed6e29365eaa4831145e3e5544fa207e0eb0582e20493e7072fdf5557cc914b5a9a73566115f97718c8379061e85161db465ad5169ae1a14093384169058e428c1e99c165f7a3845e506dfa5f0292b94466a21fe85654e0257bbc5e6770f6c733ebe51950cc9b6977e85f54cbc66960ee5b1a725eb99a8e2ad111db455ec24b675431519fa5d7d966128993f58b53fbe703acb8c4e49ad19daa68b6830241d7d2112d8b716fc3c42eed41944b5b1cfd6078435088ec102c64b32a432141b19ce68403d22e91cd31a8189f20c32974e4ccdc4c3b8078bf1f8bbdee7974e28a0cc9b55c3de9cd7d44a1dbd898696176e6b01398de1b4e70cf6abcb7a1f6226d4152eb387b58e0cc7f7e82f64521aa4bfb079e606ca1dae4b6f88c131b5cb442f6fb44c3d7566615a1175b42ba01a0c76308bf15b0a95d1e5033760ad8f3991be9c91f74bbc19c3f60b46d944870cd603ef49bc72c8abd46e1cb2a420c4d4ba6c820e227b95027f9ac60fa1f976ece0431e48dba4544471092461310eee5bb539688aa8405237d2753a8383f4bc9e2eb154aa6ef861aa6b0dba98e5370f4e2d86fd8ff2a4c048db77d979b70b09fca9d68a0730c587baf068296fb23affc26549eac5bed73b13965bcca324f594e16aa4649805164ad59989c0201ec9250e1d41f44b187bac5a0104b3f48831bfdfb36a18f971f1a86f28f76e4e1d6085d760da3c2adf9d489b0e9587f79685fba5a4516ad8813936b94124b15690cc233d2a923625d2956ba1b161b2e8c17bafa1cd9ec37f5ce42aa6a6c1aece3678edd5ffa7f10696b9462c76ee6757187c475abd8a15dfc6f320546855f7e64b60e1296edb9471084145c01abd9b700cf69462473e7b08f090b4b6aec4e20bbc21cdf6ea6dd76b598b50d390a1cb82fc87b0f1c5ff275fd2bdb69583ff97348354f984c57376133fa7259b89c3e91f40c5b35b9ad07f7b7bb4871bfb663dc4fcb4054e3ec8408a1c8ca9ae933ba00027e823cc28aaa012e5a5aaa22653c1c3340af1adcd2032c0ff3a0f079eb482816f1ed6c43771bb5496b71624e8da4fe756ded327e75c1a6300597bfae3a7dfb9ac6fc939bed1477ecc56dca29c370ca78fa8d104569282a804e3c0b3215e750c89705e2a9867de5a42fe50eb0a2d9ccb5f2fe4deefc0b799006af9e2979381a5e45c34bb771acc8b1a32180468908840cbcaf845fd95e0537079206d26e88545964145372908cdaae8eed834b6fff827dc9247d34cd7c792d31723c16e6755782e058f97adbdc8a5294b462e8d7d246090d3d2aaef62f77422c924ef25a13181e2cd0b42131ffc0723d6a33d9541198f31a0c8c41ab06c4e4eda9a626652af4c0ab0a9c780535923e44e4b06c5c584a47a8959e1b6e97e3c98f42f4b0de5a3e9f09f1a7dc028d50c1f221de1ac336033e5c04bb6e6c5ddb17b4112ea73c46631446e53298c056c62154284744c295932f094f8294a3ab01704f2402ce75bc4661b96ec6f0e699b60e75bde0bd9d9348354eba4afea01c558e2715e885eb5ff4c6772160add7863be2cf2635046f1f390d7b9b71e25571bd7a142e9ecd395ef5ce858cbe522e3ae0bf108b3f7efa5d9751020ea694449693821c66fe9caacd2a59afb340aa68054ee78e1b39ec5105a2d27b979902caf9e5b90e955efbd330532e95bf8499b9846bdb612616deaebd5618961bfdd8627e0681ada4b77c4fb0ea3ec643027df0af2b6e8927ac2006a8f37b383f065245837b80eb2878b479842c510c2e3c8b4b0ac7044872edc20fa83a3c9252d4fad8728cea1e6c5ee7629e7e23b779a3d7ff40e8e9911216c0468da18fa1f61cbfcb0316deab88a1ef34abf47ee3e1e8ec484fba09168a0f85660df6450ff588e42353798c43c2543baec5369ab6cd427b33f233b95848460d3a75db8a12296cb133837ce96266c5c8e228f83281b28cacbe163dab1387385451edccdd78c14bb970cf879a1750d22aab62d5dd5c57ea2d730154e7e4ec09da8ea15729d23dda1444024625e66efef593ececd704500775a269b0f431903a3b6f83d0ac3608a42148a25230c7093ed8ae4680dc20df1ccbbc9df5aff56c5cb333e187435400b44dd2c919d7a178c3f0c2299030b0a7efc3167d4e2451884242d547a83dde02a61378a244b414c3018079df9c6143e7a3615b708958b60bb9b4b6518a6877b9b850873c8328ba6236fcf9984ccb368e89b807015f74fa0a80de0dd506a61cbda39bb3700988961f48fbd6067144c6c335059ad497467978548f9ebaa6d201aa42297ac9d85a682f7a456ceadd79a3206d2dfed581865c49b16a3ee462460107ed8cd1e11f7e222271eb8b2640bf84bf8a8241b1d839579e3081e33d24ae0919573e2e0c179f0cb40608f6602661b4013247b316102f9c299599c5bfa0c9e3ab15471a453ff5bdda75a72929e93d1cbe111fefac4b550966fbe6c2a2d2ca8dccde31dcdcc8189fa64336c7f304c6c2465a116b5d0d40a0c6ae388d5c49bff882fb4e90e1bf3648e11b9f6d20699283811de48de3d5f1a70f90e14158b3abd001b5d38acde7002f91eabdf66993f668e607bbb261c2ceab158f74d5e813db945f1f312ce8ff88e3164b5bc2600a999beb0fd8f7cb45bfd1a3b95cc6cf89db46e38264686be43ace4012b8a4796e3291aaef33a10b74b54ceefa13332e8d93bbc0614612ed5af6a3234ddd5f51abee93c726664a35a9172e71cb10a983160214d3922a8656dafcbb968001706c47428419eb21ad298e817a6b6b40ed1c08e037ebc40176b63fa6b6f71f18d2547aa89745faa0319c3f1c69e1612142edcb879ed9459a06f3a64f72fc0b8aa03377984fc2a2006042caf069a550584cd1cae5a7eb37c74d876c483da4f1074492c0adcf441a8dcd4b2c6a13366d4ee74dc686ec16b43bde595ba2f801aa8f971ca308367e5c0ddf428780374a581234bd21a0648dd38fc3f5210e0de6d813f42a7fd62114bd6af5ba6aef0681c9a0e4f5edc3240519e6f9e6ff9934af5a92111d8d3456ef1028e62515ed4fed47017491d04a4012db3bc8a2ee64d2ea8f325e0294ed8548df2a31d326309cab1c08d9d3fa394eea20e5856386be3085d6206bf4f71b6b1de94eaaf40f8e5e6a2f2995652b86096c2ba3a335867c80bbde26bf291dc92af5e87861332a385ecc77ef0ca2e1d6466360c3e82a828f850f419cab7d4f788717600164142779a8682316ebc86171e6448e1c725162d6859c46fb066e0c028c6358e8b441a7803ed32056983d0988fcfef2c20a25932655a269fbe3f4d54123266f2014a34541577363c6939ad92f16cbeabe02cd88e8fd03a0a015ccb10d94dfcd7c9189a1d25c4520d900d9c66d0ce1268ef20b338f28f71b1f633e24ee11e47773f2c0fc63102534f790c17862f97966fdf61f1e402bc2017978a71ea211306839cd42e6cbdf9c304164f1ff02d7096a2c93e379eab4d4a282fcdf9e2c99d64b2558add3590d057139e5309ead0f85b84e7517afbd8ef9c8a2c5546500101fb6b42b142f3658471e963609aa1c235ef885d893e09adc91dbf8de2f161305f546556a0c796634c2e4ce8738ef3675c3f8a32ae63ca8eecf8bf380a69de58dde92fdd681bcd7f8cbc2cd5d9a48da2e9f422cec80a5a3578687bcfaec368ffbaef3cedf4013d9a4977734668ffdac75723e3e93b22a5b123d8322e3c218cd44dc567049af7bc81f42b963abc8f0289d154f8e8a3a093430f123927102ebf049020cbe9dea0e4ff4e505dae21d0a2c3b62ad01ef097ac1e04361bc7fa300b60b8a54357bc7911f382dcefa20af8d257fa615412ffc5a3bd223fd2d2594039e3e8f2a2918da44fca1f1112b8c1e255c5e864ed4259704b002bb2031f981c485f4494be4a615568f509cad8d35e134c4f248475d10ada9ba46fa0eaacefd32de91ddfa21fcc2372b5c403732a898fd1cd2b5187e9107157c2b25f5af4dd13034085f678c8314e12c7cd88b933e928e7e4884994afbeaec4f4015788221020ad63a323a850f1e305294274554c1bb93c513b8aa343fc78cb708055d17cd36187617af462871c5c0081b7c8d1101d5b8faae48dd799dd017356890722c4b696ea5e464a330fc23a011fe3dadd4433550abf7fd0cd9acc34b7213457f557e48d0411f74ee412feae166eb6a9c663d9d664f5a34f87e4e17c4f2412d2c35ebdd898549c9ec605613d2abd74b6ad39ce0d0534ffa976e377a5dfae48432d0dc14b5d83b29e1700d1801d4dc150fe0a7c7e2887ed95697ec5ef652dc1cec9ff73986ded6864cab4ca00832f4a7713747e7fd9ad157e173c99373296aeeea73afa4ee82e200e53e313f4f29a88221dce81e6870734f300a80abe3a613cf6deef8dcc6b37a0551e9d7b9e35d417d9574708f4b2ccf4fd9019958bd6763cdf3565084ddb48228ec05810ac10b06981544bb8ce04c730220aa14754035dbed7d130404e64b6a2f1aa6205c9b404ce9bfc84da7c13365b65f8b3ce592ab02c0e19e1697c3b9cfc4b8be6acea2952998abd62bbe7d9e5d0bf8d55ad80404ea1dee98425881029d2709f739901982844304ff4c0048503fd49349a0fcecee5cf3e9b2f48420adfab4e845de6bf3e55a02deee2a023b02b401f8a40b8b384bce23f53b94af0d49deb69e9bbb7d217ca886b4e9b04b72d08ec8dcc934c39fef86509aac0bd1c145e96b71900e825d38fb16090c55751dcded9f26078a08b9377ffc42fa10b044bf018440831f2af46b00309a1cf130c317332eff071af3b0e7e99755327a48824197ca87a966ff3ea827c76c4cf9477b2543fda14d24516fd9067b7403dab544563f07b4db5318b8a6ca12ca6f234621da3b7c76cc0acf167374caccf2251de2da8378d15dbda89c831f117067ef387eb1d0a185705ab57c3e6384576f074757e4588048c0af03829ececcacc0b04316479b28a2e95b6638c01ab845bcb2e4a1f31c44339e0f4eac80d26c1f981831e02209e8e26e0650012278368dcec779ca0760cb4c85f67046b025de2de07a36b3c4b0628467f832dd1e2a1b3dae8964d9f79737ab973e48be22dabbed1840eac35796ccdac0de3c1cbcfbe1abd012c62dee49fbe86f76febdef00d8cfa4688f499c14d7b818a0aed037427a48a20c1ef4e1c8c319e05f4bc16a97c0f5044ddfea28554e9b4bc1df754907dfb5e3029ec7d82ec10d6706fe7709b97bf64525c454c5e6d69acfe8f020be833b8c06b5c99fbd4ae2a49ddb953f061a83f6370d446fe02be4a92c7583cb364330c03b031ee2b84923d7d2f1bc6242c8e5334170b9c03f1c61c8cf11c65e29f76079214a59702a589ffbf9900f6745dede6b1e70831876c34359986fdcf1a92ce8e2b19b43ef556f888eaaf3794c0f116ba0658e0a1b20062c944cee63ed65d2a350d8f60e03766d1fb79cb16b6ffb405b7d28ee222d64ede22f0102584c8795ea128b1bdc602b27b7af150a07b90691257a73ce5146bc180fa545f9d2c10ba0c28e11a4c4a9b4b7aca5e65f01caaab461eaa031d106e58e21baf6d5c8ce3d3f8768c434e6c203d318e630e76876d1115306be191c23d3381610e44cc8403468551664564151a0a7aacc8b2820b6c7dd3068ef05d9f766a1fd2131505d30b09b9883e6c12da3068815213458694313c32968bd1b4009e782b6b26b01f620eb45e5fbb1c2ae87e6d0dfdee5f84feef65d62d819c6df42df616d5b73a75fb136154f92f856ef42d7c08797479f3d3e20b36f35ff92192ce79d1092c17252f3916be10fd5ba460c140d4055fe238efd53bf6ee142a8ddafd0c3895d6709e9c5b844dbc496ee33929d8f6514e51978b02855fd873766d1f959aa2f4b1516926634516b8fc9837788a4563397cbad06386d5b22a77d18e22099e419e02411748eb48fc16319ffcb7d7d36866831c3df9e1d35520e0386c8fb2e51627aee1f2d1f2b8bd31648e6bdebc1917dd5c0257dc69b2f9d3c7dcd56ee0ff81064fb4c008a889a107dc3d8bcb0dd59cd3a79130d96491cb885af14ce9554d32ab8ab2450523ac1aa9ff48bfb10be6ccc0933e5f15b131eda9cea1ff5cb3f1df7ec33eb43af3ff63d352881d6bc5be9682f9cec412d48e10a31f3c55ae61353d03e172960e8f220e20f0e4c883e0f00488e050c510a277c37e75aa6bfe743c954c5dc907ecb6ee83bd22b16f424c621faa8972a895b0c57074bcd33ce9e7e99a9e26a01fc20d9f3d18bf969bdfc19fc34a68fc1d2e543ddcda06657fbffe278f6da1a4b6b699af73f087e4cfd00b2fb9b5e0abe07b833e4ff7628f72a526628330bb8a370b940e83f845988a50509a3dd7835cb82030d2ae90a2bceac40d5816e3636bf7b6dc1bc37d485c3580495dc27f79144ba7f896c4f0a820cff107edb755051da2bfaf864e4154c87de638dd67df2464e2a7b1c2db5969501ebc352baada42a2bcae830a0aa0b0782559ffa1d0881c098ba59c68569061e4920f67d70dcf3bb175f72b4619ddcf0b721b7eacd6c6442fdce473adeb09a5719317a7ad06bd36b1d5ac252922baf8ec24dbb52d35581124d499439ca196093a03e9391d1a66607e0351e0a8f111ff948e47b3b50bcbb83d709556870beda1f2752ac5ccb1cc1ad4351e7dbbdecc41bd42304fd7d1d2d2dc6369ac58e1f475f474537de3e2f6084bdcc3dfdcf4f0598bf4743e27c2e91a4d6402f697d7fa5fd956872072ac10e9322e7fa8cf9b7792d53cf914247b0c3ef1f76c1d89d66c573cadea75983ed66cfeec48d07d6efe1d0c454cd1b6b1c1d49c17b348ce32593d13281e3db979470e4e905defab1b95aa2864e03b1511979271986ed887ab09a8147e97fd87557786ba92fe5ad3fdbdf6010add255dc9817404066ffbb599f2a89516fd760fe04ea537fe2688cc52881a5c54cec26ec003e92196fbdd98e479c0fa072f12f6dc67c207700854dadc129cc8eb81d7345223c04337251f5d62cc737199d04a809c8072c8a2c8d3af58aef47fca569e66697ca418032cd126d666985416ef2e11419d2acf38f8169bd4592f3ec16acd12e0e75fea8fe1f62585f63586bd4dfed0c02d5aa88c1d1cb3d84592a2ffa9b8da0dbfa54eba0356a114a7d8db36b8e94cc2a09a704d3f71ecd2c36c33c0842f9082f08a20630ef8f677713fcba99604d8ac84c784668b6fd5304a2f9ed4915018940ecad4367c8813b04626f782e6f40e1632cc005ea34ad570786b2de53f0022370b16ffa64a1a004979e5b4984cd22b74f804c6e4468db7621b6b762bfd2f1bd7b6a8a5996fde009fc8f858cc4bf5d2e21e00d4f49349e23cc7a7f594e2b2715afb79102c3556b1407b2e3b371e3d4040e2537433d6170ed43c9b99e78dc936297083c4834b12ef6837a1eff44e54b817b09fe3c2ea49e4b78a54e6587877d9b2b27a72fe03b9ba88e9abbc3a5f6d1717733963a4effa1081816992bb55f375deb26cb515aaf0ce0876415bab880a07f611ea4badf212f52e56cdcdc3cd27d3a9712eecea5a02fad5e72e591e2715b1d5b99ba18467f8964b4470b0e73594aa5b58b9bfd74ee5daacb4c924326b7c9a8a0b0b32115f7d005473a599c70ff66021c523ff26357fafa8bf03a355c7bd30197da52ae5b80135ff7df566ff28b2c9b56159c453f3d127ce5951ab6232076d80ebb356fd577f28a8867d45537647d0888c535bc50baec8d854a1870c4eb57f3d5d7b25889c1f86f5724e404026b2c950dde126e27085c1a4a2c5cfdf34de8829a17bc77619aba434a6ec96b85c5374166c6de8db4aff42ecbea1d9e0b5a919e70e7cfa0a1bff162a6f10ffb6ac5bb0f04fd5a2baf1903b71f4f657f5807c0375cc469040adc9bbf58209a19271d454962da8c292cca9545248ca5aa0834b8a094478cd72dbb1cfe314689e1a0ebc454d821ed9f8a01104026b108b27ca51a7a2d3cf13511fdcfc3fc169057b1971a48dd9adadf8c20b546885a2384ecbde5de01df0b400c770bf2d589caa432c1f23308740afa33a7ccf983a59379843863faa05bf558820f1425044f48187ce0d7dd2fe89fc7b80be28cd9834e06f1f0e055f8127e152303745d5aa57495528180802a152cab144abb4ad931774249baeb17a49568a954a294d210742c4e9a5c8c49879813d892edb1dbc0abae499507aa3c4fd51ea89aa2a5ea93bbf13eb92237e06dc80e6c2e568878418660525e02f0c8dd0420871b3a9ae82808b4d396654c74272f743f56382a065f3178c10e3fd055f0dbf3e7dd0c44a978a03b75a03b75a4ef5bdd748d2ae94a30fe9612ea1ae540f7e22e4b74b983366b72b114284e9714ea569e08a344c7d2956e8f92dbf3c2f4497acb0a3c8926917a8316c88b4b81b61b3b4c5da01692e9b1591e78cdb3a92c5607b50db56d9a26399cd26da8be99aca9e5284bf1cab6906ccf8bb7d8cdce2670aa537d7bca6ed7441d00bec30e20084ace86774f9a4ed68057402d2996065dc01d3eb5d0b1fc2dd75c5cbea34a37956e42ddccf2ddb3df77297661b93f56326e4b4a698257dbd6524a6da04b5d035d2a654f5fd91d2c00accaf6b83738d4cd4830cab4ddf4ec79dbbd6fcff10ee6639694e7b1d8203f2c903865fb8f6695c018f1069ee36ec41f41c0ed7615227e0461b5acfe64d6ee05b86d73c90f3ec5a45494a7539d6ca6f8c513558f0ee76f488cfaeab1dbb64d3b2207eae0b675913d1ea86f26d3c581fae6cd3774e0bd9bc19bc09f9e4d26f0a6e7984a2695696532dd9c3acbb5148beda02d3a0864f138ee86e5cacefbc8eba0aee281b7a7e8274124fa64d6cee51fa87aec40f0ceeec54b244bafc0f32ed6670b6f8e5962212ad59228f0eae60fabfe63ded9bdb8a59b25deeec5030c103bbca6271b3a956a9b6ee87207c917b6a76819f35b7cee2705f824c0e7003e2f9d348bc667109f974c9a35a33467ab0797b3663e2f9f344b9ba1593aa1850e17cdd0cc2636af59279df7549e077aa04a3349bc994c200d5803044d2fbd06cddc365b3299bed9de3653092c8125b0048207e2a56f366f25d5c16ddbb67baa1d705841e5eedfa7f6d9aed2fd7beea0afab34eb1ba94ea5522927c1a50d2c4d0ec70fb207f05e2946f6b0bda43a68bdd7b4b6959e77b08ac54aec35f8cd8257d995ea323866816b1ad4e61119ad37ef3b321d6e57d5cc221856695d659c23969b58b6cc8912b6405952672afde8be726dc57650c7622aa5de6253a93cbb0e277512cc795831adacac3cc69587b89b951653cb4b2d07ef8a95586bb1a97b16b438a47bd7588eb27907a3a4e99ae9ae7278371dc7fb0e36d90c9e0507fc6907833fc81e58542daf99240b73adb716cbc33d1b71cae6631e605e024b25afe48138fc7bc49f8d585a09dad2f779345e0d0fbcf75dbe060d085e9bdbc802f9c14527f1f71db4cdf1802979e03df849cfbbc7c3a588bb9130f7ae0f3653ecc3419b7d780f979c0d1f6e9738c1c7d18a26aec05aa3ecf6edd6ccd56b1a65512f95262e65797ae44a28d3753a539c75fa07198429723c2e683710dc36f0db39ee66ab99a0dd6eb237ef68287b7ac9aa6e8c399d2ed3aceda76fdccde9ca2e6681b792951c0e0dd7ccede26e3c0b9e044fb00e385a41022522d00287385a2102289807a770b4c20459606d6e350a8532b1779b86c4de05bdc7c82022f6ae4c87a0e95906e7efde5928269de5d974969b653078116743e292e9e053281b3b6cc91fcbcd547238392ca71875734e28d2d5e96cbaab9b69c5e07f9041a46ecee9a87b6f2e07ca6bc93ba79bc3f28a27c7a36296fb83ec0194c1de0fb207af6455f7ac6a7483bab143d4298743c3e0fd41f680baa649ce86e92c8fdca9e583e31d345d2bd9d435d9d821f8c89dae0defa087e3bd740db429161b3b2c3d7a25d3ed7991da9eb2a3ab5ed8b6d9fe830c22e2edde0f1fc960d0bbe695ac77cf964c67f14a2c2f59d54f162c95aea95462b9e7994af74a2cf73c5389e5e66cff81c59477583cd022c1aa11ea1a91b9e46e6a48aaabbed204a7de62050a98c0a96fd734b955eea6bf209908d69938a7e5a9bf5b9dbb0072bcabee1dc471fa76f376c9f150dde301da4c31c87271985ebaa97463e9279b4d1fdd00abb3bca687f05eba5e159d77f032db3d8bbaa6a9eed98c84c77657a56f371dbccaae4a67b9eab159abd2c551fae9a792677a4ce991bb21f10a75bd2a3ad5dd2ef3c8f158bd74735657e9345edd9b755a00f6e272fc70d52b8763e592aeba99bbb4c3ee9e74caed6879eacdedd86e96b8e5a96b2d3627c129d5b76b9b55598a63e2d4b5ba6d46606f52c9edc897769875266eb93903d9b67137fd148f493bdc0e5eecdd4cfa77f30e4eddefa47f29fb3d48b3be3bbf9da64eba96b2417e3418ba54ea35dd07af491ea2a6b1592c2f5d2b59d469bbc9964c3858de42b1c9c6e5fd645726d33575b5dbe8d6a1c9847ae9a79b7568323d723c58eee8a7abba397db02f984f8fb967f157366320c70f077784b6476e63956e325560079b8ebae92bd5b5283bd081df6ebab9b1e92c2fd99ce123f8c5bdc7f65efa0b1bdba5f49a6973160f7bd788c4aa956d0e4763d5cdd90e7e72397ec0b11dfc0ede22de9ec15760076f9be9268ba374b56b5359f0d3b3f97421ce6273120c5ed4cda39fae4e6370032568fb35f387932cc542d8ac8347b7b1f9081e1ddbdce1d163b48dbb91b9b2ab79e46e6a5ed33296e28dbb1171cd2d8204eb48fc8314bcdd8c04e7f4f0fb2cb1ea1a699c9160fb91f5aae8ec7bf8f61077b389b804441b976b72c3c1071bf1b5d95e9dc638f4702d1e00e08392109a6de8b6efd8ae7a4d837795235e75d5cd613d3e626db2a1bbf9b1862ee2edce39a5f4600a4149b89c5c4e5c4cae27ae261dceb041aa742e36daf46029d624d7834b0ff7c70e36da001102622b81a592278d904c7820ddc10269172090b04d29e338c0792ad9b61e4914a08b2ebab0a129ddb330df2c0f072dc7ddf0708d071b3023988f381c18986b72e3c14a1a181b310fa5db416ae8729cf213043238e140146636ee66e6dacc0cc775f7e47422cc7cc9f616decd1021cd02ef79335662c9e97096bd5a1dc6fe6144cb182286eb92e224074608f9b15d8c0934743f801841a4593a9486018377db382fcbbaeefbfe98981ca7703740e64a47f9f61cd5c167d59b8a0e278743757b0a28a15ed94015ddc06ba33158959c40d5469fd0cb8a0833ef5920417e34150d057c53f1b369d2fbf61caa9e02b4340b202aa0b40c93cd4d059e67e920951454346b8bd2ac18062be20cf90454a96eeef0066e13c80828005a825532aecfcabbc4330918a4414303aa3ecbd0650aa4ba2653cf0bd38df03eff4284f41ce2d5419b33e405a73ee405a38234cbbb39a9a33eaf695a96a9be7cacda9e43ac52e5a47efaea2dafc00e069f296639cb419b037a2f792fb18060cb41dbd2a25279a7af5e337f7488fa89c3012fea64adc4da0b8b84c88bd42bb0834b3f792fd99ceddeb5528985e5963c9b7ac9a68aec8075bc4b1cb91c157b1747ec7065757f7488233ea1ee8b17ffb1fd00d2e1246da7abed76d04f0fc630c9d072d4299542a14010044110dc0e5ef59a19b9d12975d0e6fe90d451a7dccde9dac9ca6e2557af5ca7c3096563ea238b2375991a22df599cd4b7d45756a7712a47fe935f996e96d8f4b99d3e6bd6e99be9dd3593ed2a1d14d4999e3b688b2cf1aa74ef6e364bcaf24dd2cee646bb6ababe2330bc3d8358057ebb2a853a1db4434e5f9da2acec5a5a46afdc8d885b5eb9d36b1a6529ae992b1bb18962165be4083ebdc5ea343e7d64751adb387d7b5b9cd3b79b22f25d070a7cd7c1860c948a0e8fdccdf79a7eb1f1517d8b0eeab0ca183aefa92f39829419e0fbbd5de673e6d9bc83b3f792ea4803bdc429ad27120b25b9a598601215ea5f2975cdb362e84a47f128dd1cd4bfe7a0ee59d477956d293afc8efaf79a066ff681c16f36bfe0ed5a9066cdd2c79261958a02dd3ce4057bffa17936c8d4a2f39ee314204180e686b79f4c31f0f652a77eb2a01df28251b7a7e82761e83ebbcab15df5ed14b0d7e166d5495ecf8bab7a8b76991da48ab8b7d081e153bda6bfd0c97f4b84d044d5dbec51ec795245eb8a9207ee906f708810f01ad1e17c1020de6b7a52e10e4556a240a0b4140a27d4097de249cb594adea717ba4c8132969b33ef5de804701d3ebbd0e9f0c8f1c0e120916681374b4ce44786bbaec3dd87bbe38e5ea13aeae6ec7473c7724b37bf34b9d0952e9d22258b2ef79355e82edfa0451b1d7dcd1eb3678ab33a848e9e72382a97a33e3b66732a87231f7a66e54317bbb97ed263b67e554f71bdeeaade487b0bdd5feb9c4b683146fdae2d9e66f431eb51f2c519db1767748c30a1874237a18bc61eead25dd7d641b780067df96d8561524a29a594524aacca480c6b92c381e1be31c248ec1dcaac0a5d3c0f087e5670022800e1148e555c51056b242d72387a4a3709f7d2fbcdd3aced6659baf66287344b46d1a245b3a47cd481b98db3a46856b679bccca259f276932d9aa5c309908b78971ff01b5a1acdca3ede52f8685666009066e51f978f3d7ff6d803e3d7630fcc711e3302de3de61e978fb9e7c5b3c7dcd3f2eb31f7ec70211eb301dedd66028b66e51b97b79dc83da0a4d2acdcb37a50b3728f0e2fc0e3238dc7d3201e9fcd78fc06c4e33b053cfe23e21900e7f118e3433c9e66c7e36b681e5f63e6f137588fd721e3f13d1af0f81f0b78fc919bc723d1c123d31280921f98f0614902981c600a4c458dc7cb9f666509a559b97bcc2b8f9756342b7b8f99f41c8f97539a9545c7f1785965008f597bcde31b8a398384dae4f0f8e6c1c1b67c0610635b3e3c7ab02d9f1d3cd8960fce8b6df9dc04c0b67c8470b12d1f1c5a025c655b3e0a28e229dbf27180bd2d9f0c2417711e2905f070402a4504909b1d70055c24ba226e5640aa081e44f848e1f0803b8405f2000b010b0410dbd91d4052403cc001079252c08bb848642920330e440a0808dc0cc4cd40fc01a9ab44ea2d1f07dcdc630fe42ac0be887b95e8e12d9f1937f7a43e0388d48138112a227c9c876a88ef50f1a0a10ae244a8ae12aa9e7b1e43dcef8879cb87c6cd3daad30842f520fed9964f031870946df92c800818b7e5937de4218e83e28143040ab5c3c7cd449cc745a21be2661ea8217076e840fdc0a188db80e1a308180a8021c3078c0ec68d0f948c2288b80f148f0f7191c8503e58978192a1809b65dc2ce345a0ae12a8b77c88b8b907c67d9c078c0ff1abc4cb5b3eac9b7b5067c9405dc6777c3b741ce7b3f19b0f87e69bf98eef2af1f5fc3836fe1b1edef2a1b9b9e73bcdccf7999f6ccb270108388b6df91c6047cb6df9641dd9c68560c11162070bcb8d8e9b771ce722d1d9b81987c5861037352e12580f1c867861d3825bf0102d3c5a7cd0d1d2b5601dd8103bae8305e7362e12198b8e1fee030b8f9b7db8d9870fc172956079cb67c7cd3d2dd7f102a7e536947079cbe7879b7b58fe830f2cf7e137a79b1a17e264737c91c884903909e037a7abc4a9e7c585c0c1e6c5310e578900bce5237373cfe93202385d0037d9964f0e1c0cf0926df9e0b859dd964faef19a8b44966d8428c04d09d7bce553e3e69b0b7191e86c6e16a2645300ace62281ddc0c106785b3eb9e6045811e003580dc0c60a67e5d55875ab01d4c03c1b37af5112e2361789ace553c366e55e09e766ef66ef364a5789d25b3e3737f7ac5e031462751bf02a81c35b3e2b37f794bee295ee1d5f2430dc63836b32dc6322c0077091c85a3e051880bc8da93bbe486c5809d35b3e3537f7802f404800f003b84874b847c96dc2ab44f8968fbcb9c774d9ddfcee359346103380a09961c99011c00f3ec4d81cde839de7c1c25c24d22687bfd8f900d81d2e92b6c9e12e763eb43a5c24d32687dbf201408c713b8a0ee371b0f3d762b7b6fe163b0c5bffc2626fb1f5a0c5beb2f52a3b7aca86fed9d15136f4931d9dc5866eb2a3976ce89b1561cf5e53d040155be0158b2541091572803b3b51a0812863c0d25e1f104210173692ed19dd56e223bfd9e6b117d99ed0edc198f4d4db33ef93bc837522202f7b48a2ed7492951d9aa477a624dd1dd08e61cb90a7428831c6cc5229a1a0c566456aa515513a8ca752220c941f2aa690e24914503cd161bc754ee9a4096d49e373adb572d289254c2891ad0e250f92233a44860831a2a3f47e9162d7e7adb5333a837408249bb9326cbafcf0d143c78d1a3534683a8ca752c6286727e91dda2a0d48200904458b31f274a2591d994829e5bc31ca9cb994326762153f5858c233e50f175b689145fc7e6413299878a267b69f98e289f7d133d1a647b31ac7c734d64b9ae544ffb415dda4a3c0b29960d94fb0ec29b06c2858f655abcc27d914ddcf17e552c229b897e0bef309fa233fa9344b0b9e6e354f87cd93e514c945b34ea5a7c82933283b42759295b24c8b32a3cc49e79c73ceab46dc4ffa868e0e65a9879c825b4a799651e44fd7dd04f79950dcdde3c6123a1d3fe68cacf76ece6a77f347baf9f5a39bc398faed669a3c4f391b8d459762d1a13cfda9116524b81f43d1ade95086fac98c82e56fe8681696c9211228a38004c27d6bc49f9a664d3abfce5d9d781d5202d09b153b0c42779cbf70ae01e70f7f1d63e7afbfefd6d0cb9b69d4761bedb69a39938a2ef3d3e279ea82e77da88934721fed31818050032c6f4dd322bad3675b47a0ba04051bfcc974ead789a133514a1f04fb85519d2a8dd449052db26227459d4874b3e851f4d0a3cd0f892ebab1c350945146aa53b1ec26b44965ba004937907073316a6ea36de8e4e72f2538f482a326ba421401f4e64925cb3e118eefa66c00eaa6e0f8a66be84cb40a15ec49954e4e201cdf92d46d61f68c413da31638624163116ad79641d8903dc858041c0f000cab5598b42515e8ecd884177a5d1856319ad5194e9a65a1502856518b6edc44184d0700b6ba5d58968544dac68d483c605b968562422cc4d1c45ca2aa51eeebd1a5247d1ded60b2d026b5ec85aaa193a2ada3db9645980068226cd3626c17572537ca468f744eda210c296f0e5dcfe24cfd15a254ca5c535e128bbfee9cd87cd42e89bd74182f994598d832daba892ec6acc3a2e8e6eef26a899a264b4c9f623eb0dbae4e26e6a7526f96da244fab2e5cd9bc92cadb62a94b269334b1008025c2a4bcadb4752651dd44976597e9a59a68f649d3d0c9f727b193890563395da7b0c3785a51957e33a5da32b9ca4a2c5b9f240a8b9e32afa068e8e4bf4e4305c1d7a9cdc734c678f371b441748f76e66414bb4e32a5f5a7a9b6c8e1d067593dbde23c8c21618abb89177d1b161fb1500a9b5776a7bc97cd1da60aad32109331c2e48884eb45a58f32adec8bc3d64d74af3686628432ec12d1d5163628fbdd048e972f6884899f2098dde882676ed36f39ae2d7dedc526616c7d9778ba85dde8193a9982e926ba4a29a594b64c6a812b681a494aee46f6ec286746b99b2a83935d1786b515580a86611887d338931b1d0335432727499e54868ee162e2cf180e10b2e982ba953174b92b954a479e90019332a9e0783a06cd64a2d36432995a4692966197a66955a313c482341963d6755269f3bca472be4a192f9c65db9d2a2f2164e10c27a5434cd3c6603218cdc4a2d3cb18c4a571339b8926a6d91023136b8ccafdf502bfefaad14718f9f0f5224978b0768cbbe14c18d7753286737238280e4dccd91aad1b2da39f0491ed1977a3dd1a2a9de4322f74211a9a2d43a1500c8d22c57287ce192343d372888902a697508a685e56a8e28a29724993214419638c3146296394523eca18a59432462979e88a525a65660bb33ef5f5594e76a3cd75713762bddb9d21f87526baa45914d39e39dec8b0eb3ada85de1b44e86868d8970ea58ffca44dcc7a55db211c57708ca733ce286a4fbdf4525e9ef9950f06348f0dbd3cf3ae8a9036f3d2665e243e0888361b8859d8c8f3c42c6c8ab091ef2418b4285b291c87900410ae220c5270ace20a25385e01c72ac070059c352b5611062af00aee6b240ac417995d708187c42c22bd949702f32b1cf1b27930bd1498779503cf9b71222642812d68b1005d1cc211a0c0b18a274c79c1710846e002cbd39ea9f966808024d074911f3d26ce5429b347e42217b948ba554acf3cbdf983c17511d774bda2c3be554a9dd232e4a710babc83bbef2ac7cd137082eb23dede376fdd560b3de2acebbb7511b77cba0fd72bb63aa5597d73bf929eebbb5ba5d4d7e72a25a7de3ae58a9f8e926cec905629754a87320fd9e64f277a95d2ac2bea14a9dd88b2a645a7366f984e2cb2ac57b48b1c9166bd55ca0c4247ba13a84329cfd3f5b5f7b6513cb7db333fe74db2d9f888de77c88645d74477456bfaf1665905ea5ca9542913085d8e3f4073a63621bac84f01cb6701cbd72f00cd99689345ae4a8930b24aa1320519f09439a5bbeb50775decfae42a45d22aa5d2634a30269a1585000628581e9b0283d233b2054f30279a158760842660a6d9e4e38c29913f21c039c4946c98122c5f6933b9d1a4870b7ebc20080c843c41a459591ea109969741a84e2c6956ae3cc03c8833da0b385a71058873fc895968218373fc41c931489ca51317952ba84aa9750a1cdccd6874c308330afbc8e8126975dcb7e718c4b5cee421fabcf947d02ca343a4c37e92de0925913bb36a540842c10d8e40825aaf2bf66037005dc4314675e29b6ac0f9d99422393a852e7f58c6ae99d372a75667ee682bf78e60efc60e576e462231e51eb567569b358a8ed317c5789c95c79a9e16af748e76d26b7a8e462befe3ac8cde7d7a9c1e6999cebcd1381c8d49a64beea6344156f7852f589e7237941e46f6545637b97a66257eb35697a9679f37bf386a766f392a87aee0a89f37cf539c1dec3dc32bf1daf0bec2217a3c8e287ade71e2ce0a7db5d93b7703748f43acdc744d6e2ba36bda111ef3d2af785f89ae0dedf538f5a2e3d42bca478ee0f998bdb3d0ae3fba5e155d5f9d69a237a77bbc39304e7526a65767e2ee52183948a79f1c0e182faeeaf4e6964bc1ab7a733b523b52cfe8ccb81cb93f57ae89b65196ba3903a12ddb412f5db959759db9ba7907677775d5c7dd7ccfecea28abc2ab2bbfd1e7cdaa6b994aa21e391be0471a7ddaef9dcd4770f7ef2b4faddc2cf10abd14d5e378af9be8ae70c48b8e132f9ad3765fe9b9eed9152bf17cea97a55fe1f0be729c951d4cef0ac7cae97156b8d339ba39dfb5ef6a6de3e8b3f3916b7adade733d779a1a6917bd6d673311dc3deb10b9bef2d804083dded82e2b37f7b96724b15de2cdddb92a3222f1688e6ecebc46ba36afd9585959a111afac7ca4450e6707afbcafea47dfc1de5dc58bbe83a9f5de967ec566895770280e8ae39d3e5a1cde36b2da2387b3f2d48a8df8fbe9299b93e01dbc5af90a473f1e6707afdc150efa95e3783713c1a99bb977576762ed2bdc77b026f1f7bd667e9674b25908e6ce62f311ccfd9b33d4a6549af31a91385870d64832c52b2b3573c566a73623c1a49e501d691abdd3d2d0006364bef0c5f418dd076e1d9e1b5d59f144afefbe72f30e5ec9f0f43e2df7c8adbcc8147127d9887bae6b93bbe1b0bc3a1367e3b69b3591c8f660d742a18c89094e4af1f56da1a3b7f3c0ec39a53b2591b58236d064dc0969f3f6fda470398279d4bf8c4641fbbc9039d3a7272cf4ef7e7346bb22d4cd59566fa422ef87a78d909965353d4dd009991dc0530378c635e09963196473f4a4e39ba7941022738645895c32d2a0b07d162bdf59d149b67e644de7bc6b76e591ab69958d362cda8f1fa95b4343131f0add0c60970fdd0cf8f8c0ae6720f4beabf879441e25a47f7abc6c365d48d01d1f99127585cc3e51c12809088930335ed145eea6c8eafb2b208b9c4e7f3a3dca8ade6fd5cb9feeeabb3d4277757ae83b3658e83efa2124a2f74fd7877ce8a18ba46ad2ae4e97dfb169bb3add9fbe13ea4286342b26a18a169392ce14d9c2708e4152c97c52851653c0592e71a2841638cb261feaf483074f3c570708bdef23f4be487c4ed72e92eca19fae0fecf222b98e65e07abdc866c0c7c77557a76720bbabd35d1da07fbd08f97a9d5a04441b966ab58744dc3ddb7dc5921eb91e2cb7d5eab28b5ed3970d9669f3a379d27c37a38d90e93283fc6861af6f65bf2eea11028560737aa09b1dc89c2459d969da6d51674bd9fdac76cf963de7a4731ae119564d3dc3125d644b0ce5c5e1184a9c7370ed1bdf338bf9d24ddffd3a1b9315b372723732ab3488e8728c72a3593a7acc78c58fa6d4521a1dde1a1a4c43690731c1f9f419a54055c9139cf04405590035090194afa5b4a00c381f67314218c112274e649d6346d9a31ec9ddc47b77e85a9dc435dd02cd470f1df3468735669d351dc6d0fb33449f514a23b3323161c4be6fce5a6bd5a978f6c466fd81b21884e38c2ef1f3523c392ae9dd8e30bbe79cdddddd545e1d899b1a81fef0f0f03c61f365b1fbe20c834623d39146f802be69db6049365da664409d05853211c63dcbe0484303c73f472829d5eb25922251a8e523a312c48528246dc459b372b8b514619c76af140a755917ca42215bfad6bd746c63b1a6189ebe1a2c37b29cad6cb75add3cc4a4b25b0c4faad76896ea662298e5dda56c16c393cee9a9d76856eae62398e5fdcfd2189e32c9ed98f87b0d2498e57d948d313cdd9a6631d9adb99b127582b762638749da48bbb9c3a29b658fa1a881546ec7c4d96f64b7ef4317bb357474d85974f5fd1acd6a99d046eb4f8e89813bca8de9d23130a53f6e807304ba3155928b0175829c18c5b02b06bb688c4c675796613d5a12da64574c5fe6a5ebad6939e59c35061a9531867d73d792de4687f5d4f65c97766b975a27a574d2d936c0b4eca295d56c120a893ea16849dc27dc9f4ee69329c5a46232d19f4b662813cde6a21f238ab9f21d7b8ee8d9b3e85b871c0ed1bd5a087b7f955d74b0c33ec9f469f4b77e27c27a8b06676b2a993ca2e7c983fba2dfb4d8ddadc32b8a0e85a29b6d34c3a66d8ae475041e5cdf51f4939e692adaa51eca1456fc5c11050b29594cd102d7b805aecf4d054728a6684297b3aeabd101d69bbe9808e52fd93679c02084ba993af08bf1175c6570a5119ff5ccd62ef5b1ab6db318ca224870cb9594194d8d9e192de1e1e1d1804dbd690aae9d6370c50110aef5090ece80338d0f574965532953075326868632a17bd875fc692d6c5ba88b516e74c3f1aad7d434ec0ae3df21b5618772ce18e386b3bf342b9b99ed5f7ffc8cf10ed9f0fc411534c654267ce4172caf550c7b08c3b07e560f83d6c66ce80abd8fddc7965d2f3ae4a50e79a94fcc39277d69abd32f7d4adfa743a02ffd32040934a25532a9553269126566fe3c51454a219dc8297eaca8d711242fd7c8cec6302cecafc33fae23d3453e0b1d993392c974916752258718d64b26a21d702d02f7bfafeb32ca809c83669bc3711cba404d484698fa9a9ae42674ed8ab21bd7846e03712d5a811663d06c6b5aebcb457a0dedd31c13db1ed2a535140a89eac18df60bbeaea945775d610cfb2fb87de03a925b9c122386fd8302c9315af41acd12613753dcb7a6c319ea7ea1fd826b072581f3b1cca494198c3ab4440dd57a7c89ba0ef737e79591627a752aee1e683146c67ee6b19b378c4989055d4217b1ac82dc425907854e6626e862e20c0c77cce28c0cf717e375d5b442172f6d76e72f7b44c5557e66d80f0bb06bda39d1761b12733ef2761dfa90bec46d46d77470fcd7ac79a5fd649eef3adbd1d0d799be8b3dda211b9ecf6cf7859ee5e375ed5409dd76eea451165d7c9fdb2c0dc17f9bd714aa3842942aac00147774b18a2b3081411cabb04210be3e6d3cb545305c0409fa24384698f979b391898b1899da158b6038de2ca3cecc14477c3d7dbdb888bc5b873262ec395fafbf2ec65e3f6f4efdd661671dd622baeb35a7be0886e78dc4d3e7d4cfd78b1325c7e345304c9f615a99a06114c3303a69bd2257e426741b12639a48bbb61832e108e2f87cd3730c1ca9c9d26897f9d9591a126b72a73d633a77bb6b225b43239a53b3129b6ccbf4256e1342027375e52fcd5ab9a61ab1c9b69220627ae921f72843f3ae6132f628e41e61b41b7237dc6b26c9e61dacd1d0a8117572c88649a4bbcaa15160c3dc7dd1b44f118da1c6fda559dccd48b0487b0cb51b8aee4b8793c6a4e9709e4687f334d40a1a53ef741d6acdd9b3e78d59bbd93c35c8942037b9ba2e4c4a29a594524ec16ee8d0d103c3b0ee1643d7fd9afe2135ac267bad71b56c0c3352f1d54e1a4341b51aed1c4ca7639f5ecddd54492b9d618817752d3a638c31d22b74d2c96cf9482d46123af9f050baabbbe86687e7943dd0a28d0efbbc9481197a786ce825a59fbf9ebf9f38253e67c674482f2d8d91b72774ec1ae57260cfc92eaf6538b63ff1bc39bb11893d0bc9f44ce8f431210bb60bc531f4f3fb7a645f97bd8666353aa4177559289336646fb40c7a8a84aca6437a6b7448653aa437a6439a96414fa37439fe6ca14bc7cc9765d9bf0e2976df217d83a1cbc00ee9b3c7f8e64ccded11628abf1fbb3a3aa447e8aedb65d1085d7cce2250680b32a803f531c607cadff0d133120d4faa48624996c1325a41676c1619c2f0c41631f41d4a8d5d9479a75afb7538ef8ad67483b48beef72342179fbf08449b8ea0490c8056b0849f14bcc18994288a332e599bce49bb4a7abf2e765f16f954b22ccb4455ba8e30a2d0cd599665a26fab1ba06ce8faa1d70d747dd19431a956c9d55635d0f5b32c88ee60c61e0f630b8dd60bcb42a24c44eb8565212c44a59d4ca1f5c2b22ba3f5c22a56453ea1522f7a55914f689df1a70aed9c559e96dddd1d92212644f13ac51e3b0c91224cffb2a22eba2344b70886e3753309777cf6ac66d305fb75631631ecde385d9868940bda74522ea6ac314e259d3fdad78d024729706c2a707c22bac477bfc10952d61a92dd72ca39eb9c95448a33ae391ac51995725c9c41ebb6c519f3d270cf684c24caa1d085e539eb9c75c638639cb456cae262186b9d34c2cc3bb1ce628c31c6186328c3442dea82169b25654b396756eb5ca269dd6ab55aad56abd56ab55aad56abd56ab55aad56abd56ab55a2dd38decb268067a2fec0a1c8f6152703c354397332ccbb24c1b350ca8121a33554295501a8f34c11289132c913841c2045325d20a9a94b2bbe7c471e1186126d763dbb278b5c07106c94bc639a232b39840b5d6ebba32ba5501ffcf9465d996519e186178f00bc2d1b4c9a08dbbe138ced491381c89b592575ae94aa552a994d2caa069ad4417af45ebc4469be5136b6dce6c9e4ba6b4132af2499556a2cb198e6ad056f111af6c481c6fc412939ad668b15995d2ae3289269f75fdeeeeee6e493fa5a4934afac99ce1ee70cb7e91ee501e3bfd7579498cca7a8494b788bc39f4197da673f63f846c7ebee8a03132319bf68e46306d6ce4c338534c69b53b143b5604c335646485e9cd7986fb5286ae910c4bfaad8b15d8c1fdbe3a4530dca324b4c97ab24b233dbda8acd2093e82d2faec3232b1bcb9d29766d1f93fc1f3319a55b1945a841d9ce59bf2f0b46a38bfc46d92905dd8f8c0088a5c1229e514917e87b624428bcdeab249074a6394b5d20c7b56ef1f67c7d4396ba0492ab179a0c89e74537c3f8f12e28d064849b68489166350acc2132593822350f61c4393655f3b8931fe890c60411a3daedcfc753777a4dbadd1cd19e0a2a6b3a0499a7038e2cf135854d9e282c62c769acc08858a8e81753283c18cb2fb2bf5c61972a7ca9682169b45e575d1ebf28ab123d12d747252d9f7a5431ae3baef303e49efd4a64858810f64341a4ddbe69c73ce39b5ad7ecd021f23143d728fd165fbc8c6e8b2b97c4a088b900780e365c499af0811ac69ffe64c96c9c881eb69b24cbb8925e7e02a1fcab0cbd46dddb708125c65e28ca67347d417152a18010ba6c439897478a4654c7aaa858ec83c6285b48cf9688374384fb130459e405bf998fd7991c82820e10b3c364892c8102c61041e9bd947920415862cf0d8cc2349429d78828acdbc3ef149280ace10c5a6af8ffc8e4d92963eb418436a37f1f415d37ec431709f761d52263a39457775db35477d4a47d73c66e7bcaeed0a0992cd67dbd442f7d1b38cf40aec60ec5d7c3d6673e2abc43e391bf45777e38874cc921e49b747c96db2bbb58bc4d9e866dc15b2dd2059ddeacdba2c74f49d5d3439d085ae3d674b60557ed3451ebb34228cecae2ba4de2058e866044a4277b07919e1890a7830839a24215b82659ccf5ec4c46806b4cb1f31866ec8b6e174913fb0d0bdd143a3d8b317813dcbea3c765735da64580c8d282626c378b03ccf9c5955f94cc99c59d5471becf287ec42bf21eb65941fd7bd51e97cdf8833fa5ff8b2d04d216b42cc95578685a08edf14ba262001779f0a919ca2c3fe6919fdf981ee334248b3b0e718a45dd99bbb3942bb344d14dff0838526ba6a3645b3a8e84b2a728b9e911a008a4380d204f714dc520bdcf20adccfae288388387eb6ecd10505876ebe111d76d8f5df9c8936fd6a3f0f74f4761dc882ae8b0d4ef8cc0f74f1924a19458e26e8e28c88a5945fc0320b587e8563a79e5228641451545e12ba1845fe982e724e0d7cb467866cf8eba84629add8c4e6f57a43bb8e7237d71cb2e15ae9a5c086af9e4e3027d90cdd0614138a8ea259d7fb494bd154f44f43c191e69692c5708b92058efd8305be02472b70dc74b0e831dcde1c0e8ab5ed0816c5186ed7684301c5e4724cac3d6e9afc95d92a563c818fa038b7942a1df6b3a882fbfd647e5fd701a117c59c6cb27221d62cc3b06eec1d0a6559c8ea501ca2d865fac04d1b7159a623c5b09ba2d36b6bee66946362aff348975fe948dcd5a8c8f66cda26b5cb1d18d18d3ddb43f6c668977ee56e1e4a1cfaa689280e856cd8852e84134386bb11dd1851f650e85287ae72600f3d748d509c5d7ac10e9be259ad4c8734315ce8e4734c4dd23ba219228146a97d99b466d945d9cc324a29ad174d18435e703dfd00a5b5522abc9768a1d5e3b18a2c7081e7656a7c2cc102cf9b7a46da4459ca9a1461e6358d740a862ebbf7958bced9234e473ddaccf2782c508163a4d0d4e41820325788827347034f13ce3b47c408a39365f6082345305c5f4476818b603a2b1cc7dc23e66e4e11d905aed74886b16738fbac9cbdac0c8d96d922376a582345b022343231f5d9af634778ef4eb247988c4cbc72942d720473d7aa5d491860f9021cb96aa50b701639e904470e23d922478a6078e59ccd319dbb96d9236eea2d82e11cd4eb23b7037573ae67b81e27e213cb35327176f3758b60987bbdc9926c4e77495fb1d9bb45304c7a96fd38bb462626fd6856ad3ff7f91e51e0791fcda238abd5669291c9d923b0932eed1145305c6fc67ebdc8119c43ba520b55edc608d3bdeb48b7dacc66367a8fdcf3c419f7dc3893987b9638e36e7673ad4590e0ac4eb0c3ecaeb2d71eed5a4f12db95dc66f41861483ddb8d11863b77449118618ad4d34498f92215d8c1f57e1166be5e5387a4db33ba32ed327bb66beac768977991a55153a35de62f0e47e27a0ddb64d7e18ce9f0d7638ec1d95dd54b277865236b01962ca8d78d4c7c3d93f0c46e110ccb158e0cd767b85e529c11710602cf98661999583e495fd816022394c009ee01472338518666ad72cc5fafd799781280feba4626ae57e7c2b5f29037d7cd1288878707575353e9ba1c5b43319bce6cce396b8c898539a5acb5d65a65953da56c59ebcd145b1a1d4a4a7f56f0016a8558eb4334746fa4221ab70ee5754d34eb14dd101643b7665aebecc2d6acbeaeabaf9edd7376d9e7ac99146156c6b0c366851dce1ed1a5d12e73f6a45983a1931dce8742a1be665fd7bcfaca5e0e6ecd6a13d6d7187ea0b002dc8f439ca48005ac4e669af3f0f0f0fcd8c41f1c2bbd9d932570fee22441964093095d7cdf3c44020d914053d0a413cd6aecc3e363646868688fbfd1ac8dfb88e495be946a05b6f0340bc6e365ab59b7d7097a1c9e65130044f9048e120a1c651438c6182515b88718f32ca1e01805472b708c8f39b03ca21e05100a2014c0cd48700e97ffc1c6188639c41043275fb20f1f6c8ce892c5001263ff203d5810348207fb7d4260acc934e4c5761d9100d86dd3d9c166d911174b63984398437833121ce3f23ad818c31c2e0062e070a3164c60ba059e57a2a4cab5b2255b49b8b056f2481e9e5b245cb460d8235594bcb03a5b30d16289042d01ed102d9c5859215498a8ac11593449d920310472f2592031a447591da72b28164fb0581ad185de64a1601aadd89102cfcb8e468d92a5a1b9e15919191d2bf625ba642f3ef00cc31f241b23069091fd837016048dd8ecf709c1d3641a22b25d472464371d3cb318d2ec0846af19437a63cf5412bad349e40e09239981f696444fdaddddddddddddb4298d41d3475bf96824338a6e5584fcfc9c512469c94393262a50410a52800214306172821398c004252881134e9080042318810844b064490842d04413200001134c7ce0031ef040073aa044090738b0c4124a28d16a2591c40636a0010d481ec9d345176f78831bdcc005176d68031bd8b0863554a9a20635a4210d6840c3165b9ce10c66304319ca1014047e3a14771b11dcddd4a1b84d1b8db16d109bd25a1f638759cb88a757e87ae6e38ded22a56d9d39af4d1ba35de2435d8bd27718e3f33b397f7e80e5a38ce9275af7d424ba9ce1d6aa6dd593b6256ee3337ab55bd69958a4a4e34eadd06ddddd1ce53826babe111df6b568a3437d84042b9ce048051c91900428180949f8e9f4db462d1f93163ad44fcf99cd12afa0be72f3677586d0a1fe1d75ede272a03efaca3d9b33facab5d257ac573222b187ba67473da4ebf40ce9f43ec96eedd244e60cb5199d6ec67285986e100f74d829161df7eddd9c2179efd2fbfdbe42d72bb74372afe9cae1689c3170c52b1b8d36b0c3c720d92ba77ea8e42b18499b1a654ccd0c0400000803150000201410884442916844a8aac30f14800f8ca248784c1748931c87611032061963004100000040860668140a02dc9200d57379a4ac196ca5fb88b7af5d64008ac9b8882b7c1d99403178209922970de1f7445f1e7aa8ab24fb0ce8b51c7383fdbf4919b760c82ec1e5bf1af2d59dd0e7915c09059dbfd2ec16e03df931cbbc25f9730bf35565fa29a8b9fa5b191fefd507fe70597dd9cb755a28d5ff3fa90ce35127681de82432ef37e8a55066e3803a2e49b4b44c424c3c52a6a6a2152778a28917263bdebdfa2331a1662315b3a150c3c522b6aebde5feea333061aa81a98ee1a24d63844a4f160e17d06983bbdc9a8acb935bb888048643eb284f0a14a2aaed52b848f564e405801684f10980a952af848bb44730c76b9d35805e8d857f3282529e4f223adb220648c25bcc6cf908eb65fa9b854a9042e19db56c087caed06e9dd2f3adcac5bf2ea26226dbcb7ee29dd280d75d9b4fcbd14db269399571b7078836a8da17f9fac13fcb2c26d657f39e52a80154274f76c8b1e5c6c2592019c0b552241bb46f010ffa6c739f0702c32fd05b5f3237e7d85b3811595a1022381361132cdc2219ca9e974a3acb96f8cc95f186e0d67488557fb783957a676ed7a2cba312aae7d81a25fa2476ac4b2076b85e5a8d245f901e13d35f498a598c1767512033f29031999842cc87ca100f5628a3e30951586dfd9a701889ae3f4bd54cf1b633c5149ef860018cdef3cf56352bddbb640504f64070268d735a3a05603a81ab2904a39f8d02d1cf0ecd9dd10b477b23d4f507b4713ead5269fd525144bc0d3915c1b118034815f9574031d732b6570e5ef82dda5277b5054e0e2374c03a03407f10f546468c622078c8fa197293d9926bf021b8bd8e3fdc79280879025c1e378d4f487722baaf27c1225a0e80d2ba36d432889264c9b18a54d7ae98815debda679ebddd1f9f2a90c56e6328997ed0166330821bb64c98e80bbeb02058b7a3529fc1dfc9d3cfd9842683237ac01dba456937c40c25069429f1dc5efc646740f5e488fe8ee832bc977c6d17d2bdf97ca25847838e78fbdc620c51ea018ef8f7531ec314fa87d80699118ab1e496029a70817e59b5f0c6d7fea2e2002f16965f0cba3d06ad286abbb4c164e274b71884f9c8a4a1ceab617a15ddd629fb14a0cc55b4f6f60ad4fb8f50662c713c60d45727ac4aad5827382c6b0acd0f76755cfe774094dc126c0ca9f60cf6f71527cee9fd49aef7108335c569af42a1a87ad32fe9809334d339c528a5c6d6d6014516908254043504a1c09891984bb71a711df44e14725ded47dae2db37d2323a5ec54e93e2ccc726a5231aec7ed333a6fcb7d7ba0a5887e48a2805e8c8f2479e3f70cdfc5bfc7cba20440cfd6ae947d86f7adf5cbf8644ff31bfc20337a2e597418ebb3ae542827b494394f2ae2d9425c66af0f2edd5145b3a2bf9e05aae838040c09e37ee8993a5f2320cb23570ff2b232e3a41e634ee57b245ccafe5a6652ec701e3f69b7d9715f5e72f95d5522737e8ae654f87b31650dc788f7d5e105b44987ad29d6b085daa147497559166f7b100b2d588f18dd4abb9cecac9b824e11ec818c480595826c44af07305873c183511aa6164b5220e15b9f2a7fa9a72c545a3a40eb9ed61d653a3a34f314e4e728bf9d73239df252efd4ea58bdc85ddd3d63969069d34b68c1964c029b8f466afa77036a93c57b87d4027cf85f10ea33f4c44cecd64c5c121513a84b851190e7a6993c0e0ffdf761749e93b55d1a4680feba7f5db120c0df28de1d43743dab0a2f68f97889d76fb4318a0f53f35d4b83cfd23666f5ac0d44879a8b492502e7e69a3a426967ea3f1d0445a060db828e64a4bf679ee57c4f243ebb31bc60b437ab45cd761c493b8b7cc25fa5e5a37c3468f1043dcc2fa00f5bc9d8f859dd68cb279021967270cc59a36ab33d5df2bc319b16e2e5dff5f4c15a5b58490500d86bdcec3bcccbe7da0c5af88322d2ae4924eb6e260adf97b88604e291e6990f9ad40d3a318bed7175ec00a6d82508d2b330fa52bdcc5e5ca2c29ce1a0c207ef6e4fcca4238173e6fdb02ad8470f62c704947677a46c6a242984770b692e55635b94936720f878b5fa7c78bbae0a3bc9a0956a8b9ef856465fcdbe076fb76996803beed085011c3f06e2af96a48ad2c111f5ed69eba40d07e83e507f3456d1001b2033f7f7bbf2d0eb22cabe746c6c66de3a77a5396e15c0cb467aa5c9ebe4367a850b3cc156b45f2fcf47262ab3646f2d9cc5b4b049d478c923a4ca55b27e8130a44ac8f80ac4f090460734f9b961b6a560114628c15b9040488b63d18bdaa5655c3140cd6e3c942d29efc793d6caced31702299641484d9aadd6681349a03799276da8b7702c8c032791826f58505588e0e2da58822ed8917c5a77713fafe7eb1b67d1f8bbe2ff61310cf7f876fff2b4d41b1e21baba5fc2b19d8f578407d26de2d6c640f47953034490f58f9d219ffe8cd55e6d0c1fd860d13a5da45f6e4947ce6363dd872690d6647b826cfac9f8e05581e7c10a966621d4e3f9f067c6bfd73d1b2fe91d5c88e7bba282e7a9363e6fec01a07bd38f0fd3b7b296de6be19efdfd36d62b7729a015853542c97acff0956831ab17f5f5bf3f6f576b1f3d56f10f627a9c77418b0a392402987ecfe8d48ddb81b88a2a2475d17b9928ecdb2094920b868c33ee0be25918f4860351fbd1d166222e90094de1382d180f75361408106d48c322a1e9119e46c74852d83f4ab961dea1976a99c6fc9502bc49d12c2e3362528e8af9bb126b2bd1ac80969577c66adfee63c8bf44f11376f99287cf879f02d5a458288cbfe787c9e045802cd57c4486152563a6c3a19b697b71af96ad2d4ee75c39b8e5635bc4928a77645822b1ef7eaf4b16d913aab7cf22575966001ef4293e59c6b7fe23d14d1d95d85ecff3b9a8c738d22fc589d255404b9036f5f2b2249dfc5c42261e89692a050040633c4031efa2842a4b5df752298109de501f1d09c68d0cdd38a743b3235944b02a9318696cd54dd662167796bf02266523b1be0848a1827364653795cc8aa25c999c446619ff8f6ce0f80c28d579a418cea408768a6893793389fb3bb6071f4db1ccc13769c45d6e3acbf554dcde9aaf69a42bdc0fcf47f8cc7c1bd95560cd1e20ba6a8debe3f357409fd6fe919c804c4b9c365eb7ff3c9ce30dc110301e14416d8ed16c308c3acbb2a0ca140ba810d72ad195ae185a96d185e50e3941ba440497644bf5e3d512cf7b62753328002b213415e89983efe9c549a94186d54115635e6fd32f490d5a048d6378c503312230931326de034859cde0d647b0037d1d43f35f8bcc8fe45346d482f15bc29656f4e8e77ac22f0ae3a73e12060a624082d07d6022a9115b2998608956c2bd4398fb1789a09d59835893f10f41dbfe0bf85a106c1cb2bbb00d06c60a34e24fa5cd1e7f811fae0effd7cd8a1ed36b03463a4cf09f9905a5a4ec677563f4d5af0ff538ebdcaeeb1e504665ef1eea26dc404687a3b403e9cb0e62874939fbb30646f15ff41c3b3569d63caa8392d26fedd5f31f543f041b71add8e0eb0992c370553cc860e87533e11cfc5309a48d36f20d946b604f0254f28db6f83270f21a0881d4f05af9c934a115b5bcb0e0e1a8f10d6b69ca4e4a4ae5ed66843489baf89b55133e34623a2aaebeff31ecc5896b728f9943566c2275c7de2c6afb3c4b11959c21045ce68ac3b7529cf4e863a1bf85044c02fa8c171b81957b6d393740e09ee58c13d43d6cfdaeaf2aed3087ac768e9721b574bac393774d9a3ae927198a124591043312caa72b3fd2b22fdb75e97e1c4201d43e3c13cf38a4c7a164130533d2ef507ce5815086032cf0f93bf146b4e8a3561ffe87733855a3415890fd7b128c6d0ca7a3eb8ec1f7c099b01ae2a83fae2f1ea56310af7e14fdb0e805d5dd9d9ffb8cf6ccc7ca84225c81772b220c0888c47079b9b2dd5eafa2eca40ead655ecae89db4c8750f813915f5babc5cd3e4a9d46f930dae17d3a9c2db78ee13b4664c47b69bab5e66cd27f3adefc8026c28c11086fc2cb5fa176068f94551330654f797feed6a152ce0aaea585a6dde42122ab73270d82bf1ddba312238f0f9ef298cf27ab6d664d2f01102b8e25acb2583a510e42f472a01697368710d9aa4550c964cac0fa01b11d9ac973235555213f608dcf00039ac38ab6792496208b951fc56c63f7fcb58930236395e991ac442645b078eabe0c90ef52e17f85b849354dfc503f3b84d51a151528ab4a6d2f6f17d54d95466e3611c64162dc6b15429626879196b38ce860e336f1527d653af4a0446ac9f0100b21a94312532f518d3781990863faac0505947c486faa6ecec48236595334433b2d459df3bc13133b3e96008276fec6de8d57c37b368254b60de1992d52cb7fa10cbe0eae85f41215d44fe28bc195be8b11d642ca0553c2730a8a7bae02406fbdc16897868b0d3cb3d76ad430b4946035b446ebf8c4a9156423cd5be47f67502d1f606719a67b5b749b0246fd5dec18c1fcdf26b6681bd797b3785106b8e9a9af8f3b41706142e7407045398ed5068d057fa5061c680e92ce616cbe36f70d6e0923dad53e65265ba32e1fcff13755b077ee93036d6e6b5db7ddfd13aaa64a46be6e8a74b133735dbe94b3d38c3a05744ff8d2aac4eb2217819a6311c438f39215a7acc7c7f6f26314f9349de5b8024d5897ec8e042d19b4b5272f7d0283d17704ec836582108cf91e1f406214d88bd3e3cef5f432c7bca56adf18b4d1be6d15361f81502f748a4ac4e23a6396819277334d53050180f85dc7ad445873e2a6dbb068052f8dc6577a8dd7452784974adf286e74c24b5b18cce47b15dd25af6318f4d0b95145b3b140aa1cc8a575e0bb5d590c17fb948e6aeba3f15ae5db930b8bf647a36bb1328f8f399b66ffa3fdf30bad4b4003670234ee4b0ad271c0c6049174bc924112c477164c0ad1ad2481d7246ae266dd3437423b05a23ba7c2ba6a6b8ea2457ed13914d4f3069622c1b6ef2860337d6925ae118292cfccb60bed8fb2a794ee5b14503904306ca04ddb0383d18b959140206faca09eac89ced56cab73c8673a6397fbe6653f5f2bfbfbcc04c5c07c5ca0887cb7485307e7766edcc48b42b2603cdfbf9daa4f6f84bd4286638dfd53506928fe69a072815be11114bcde9e9c19e8fbc91e33aa647c823786e1320087b5681d6fbe6f8ce8394105d8bf06f2a3c59834fd40e0596e5d8ce3d005f81fc156f3ebfce6842aea98a635500aa6eca6e76a64a4d16626883daee0ff45ab5195d0c145e455a0d39ec110ac82f58c3a449b0aa116891b38a75e0736f31fb264cf8ae1ca0c16b74edccadb1615fd35b2ed3e8f1bd098b5735bdb96e0a1b7b773be6d007041fdb105a1d9cd50e418e74532ccab075add5e07a11b877acfd671ef4a781db0605de72e72a578f04d2efcd832b8ec13515ea14a3475d6fa8446765c9bb0729935c181ef56399e2191d24049558ee27764e19ebef9a65db8cb1846c035c958efab761c24793441ad8a7ebd4b9459db0bd29d5ceae7027f31c91a8c35a90823839c3f4be6408a474d48bf89a2290328dacf58a11130c338782278d8e4678bc0befe6ee2de37f839879faf37dbccfcb8713ca495af3c11fa9ab28c146d5083578d04be37fb3ef969e4ab70ee641d35a841a37aed598a3a2bbb3e231251a4a344e2f82c3ed7a2ddfe24ed80b228a3dc7eb12d57e95c79acdb3e1766d4762bea3cfcab7460cbad70e24ff3f37e033cbf3c0085aad76f312ff787b01233eab4d1f0757f18b5daffcf8118370eecc62597c50b3a8032af5783af4a5da5cdfc2aa3ad9acf67bcb1c396049153bc28a7026ba5f7895391d30e11ac736157a97f1d55fb90fcbcaf543b98bf3d28ef8bd5e7bbfc70bdaf83106dfd6f247b310faebe0af1b1f75279b9b047c8ec1f469305b21ac81b8b0028211ae36034ad512f80ff036baea7453ccfd633e50b03abb69e3b8d0b5264f78a37f98e390e91882f098e642274a052a232a48986df9c49e34bfd78a77f3bfed0119d7677198f36d45f6c912efe9a51a5b1c60236e640afc03e2d6d9a21dd8d29161811013d4d0576c233d9a882cf830ff63dff906dbeb28dece378eea6d9cd1cf8a2524fd03a0a773bddab81611530ab26a6b399d716d7a62b24576c33ea565429c07bf4558cae38ffb709009c436442488d5b5d2651e1ee722a164176ff8984eb6eebcaffbf3e35ddb969f5b5cff2e96e384a9e9d9bbc678d3c054fb9203586f1c9a523329eb90d07e6225ebcc4a2d092ad591447bdde49444aac1daeb692e802585a330b424c7cc4b66213d7022b6c866c1b4fa3360f26fe4171e282c49d55ee018858abcb551e953166927b63f672620908cf82146bdfe79cce7e987b3a60a80abb2f192773a0fb2fa8a163ac9bc5382dd35e1fc1562574d4c90bf9aab64ae6fd036cc38a0da67218082c119e7a68fb523f3d2af0f4fb6f2e825fab219ee1a147dcd3f5a90670df19454cb576b7a75ab6a474d9c6f083e1d84fdebc9d0e3e4f492c3e8595762bce4db93689df59ebffb2e8980c01eeafab729e3a3925ccbff65fec5af930e2e42fdfd3fdb25977dc5116614f72a279de693b26d49991769d7c7caacbbd279306476317a088befce684ff5134064482b335d47c65d20b0ba2ef77e4502d3c5c334556c22fcbbf3bce9cccaa9240fd32eb30cde1afa92347baf837cfdb621a3e89df3c0b8e0043549b1e774818daa40568389e33b6a74eb3cfefeea01e8fe88f6d7a5c38bf817f4864149ec0b9b86d9f243715cc6d17457aca4664ed7a67c6bc869f3974aaa9cf17ac2d2a82515f19e27896621cbae51377a3a964ec69f90a7f6f1d837b9008f36e89ddba1970e2c4b03838855e5469a0e6291c144c17a308ff390999342929ca4d9634a7b524eeb151b1aaddd3c1d24bacaa87ef14c476b2cf946c585d3be12fa818fd72895a7d1c622eac3337741658f3212b6380c9f30863857180bd39a8f793f61e7e86020e2e2397efa91ca5918673080d430ffa94575ffd2e1ebdbe104ab121e434181e8fe69416974681562e430faa11f4d9cf5cc2065fcf8ca90d03f9d46197f348d869f226bb0121444c37160389f34d28455cd1bb4f48962b5ac59c43d0f2aab9d4b7624e5fcc9c232908baf17355d29cdfb863798e643571e6e824b94c1dbbc56485181586b415a8c0344f0c93d1ff8b9dfada96ba46870e96274901f7d0798ac36a8561756bc98c1309678ae382025c179e59026816e6f225e991b0b948361f291487fca2430d910c0f4e7a3dbb0ca0fce25322b7a4bb247adb8c925b97b1228b6d29b4381dc5a9a66eca5ca7555cab6a14fa6f12dcde27ecbd8106f72dd66c97192e08683b84142f367baab1f1c59e90d0cbb69c00a85cb4f85566a48783dc8d90a2bdcb55f51543673122a318bc37f9c3e1fc7993ef33b18398c13e9a94781e22a14faba3347fad036b0e82482faa0b22a140cd87ddec262f2779db4b282686e9639fd6f423d48cf0bf0a91e8111e4644dc4442e52eae2a1a44277d24223e87849dfd40c6545e3525503c2560ca0629262fa250098c4f772bc5871491f0efd167bb5cb002622b11b15dfa04c9a2d7b27d20fa6a09c2e2c9a19a69401f12a32590b3e3a0ef6e28b82f7de6d517414f668b03630bb373ad60cbea204a3d17ad163e06268b0fff081eb8dd8a333b7f749b7f80320510c9391886863257ce2e57762d3e4fd538cf81f8a3c779ce8fc1781f5349eb5838570dec20f30556cb27c6c8142b87978d07878c058d0ea8d6d244744e4da4b8caf4798b6d111ef7c8d3cb07315080d28e2bf6212aa0fffabfdde00d6b60045e359e143db0005796313f74c50bb803ef10b51a4b7a9ba4fbe17ea0187aa00ace6996d1e7a63fa50c7937dcf06a5f5a57c20298c613b0c2c7d327af0bb6808988ebb2df751d145ceab82e36de16dc5a57c4df2a477ff9597f21780f2af4e47fe90dc08a15608ec6f89b85840880cec7f5edc8330f4ed653656f7d1b7a95bae5e3e3032c55d469bbe7a767e0948ec27052956db701619763ce4c7f38482307d8024a01cc493ed01b8543b41e0fab77b94a14db83b883ee4e1a45ceaa06d68414dd697171bfe9bdd6c8ddcd168b992c79cdb3468970f92fc9faacfde9c333e44a1e72925e5aa612767561ad074328e63564db8acf565d924db8764038397ddccd447174440f58bfd6ebab1df64e0068ecafda0a055a4a756a68d4a94d52a716651db44475d692d649cb66a5ba00bc02762b969fc5503b35df6c79b488dfc80d432cc3508372dadc9e98269fb5be81d47ce5be43ecbffaa8b134badc7752fda3ca04fbebd2441221df0bc9764e66558f31b5b1222e5effc80b6bf68e706e6fc90cb123005941a4ad7c181da50df22c8dd4a0a3b3f111cd6432cfe6bbcbc2f37dc4b2ad4041acc9994d96cb3ad71fce608cd76d2c26dcbee6be0801414ba9952f3e6592a54563685a9a2db3d896a901cd72e93fa82dee9a2e472192db503a50ef6e0c6f39e553b20a3046b69dffeb72dd683e4fe80fdf13e2b309f966623e9a808f4de49389f26d427c37219f4cc86713f1b5097c32713e4d88ef26f09d89f96e223e9b904f26cab789f8de443e32219f26c27713f0c9c47c3611df9bc82713e4dbc462ff82ce6726e4ab89f86e62be9920df26e06b13f9ccc47c36019f4dc83713e5d3047c6f029f99984f13e3bbcd175f9c19480b6954798482eca5aa29915a7e5ea8c77bac4f568f6f514ce5393de9fc7975d0db5e8a066e2f12894ad55c8aa510acd0f36db4533f7ebfc89e5c7ef448d89f5258492e9da79e159ff6b9eeac334d890a63004b5cf099564b9f8081a7127f92e05bc0b843aec3564a563106a5bef796574c242100e405de5f912a75399fb2a4ff81aefc990d5e745f1e2886c94da6e773d2dbaeffc5d88d67c3f220798624d5a45dacf8100a348c93b070dc8cc1a7a82b453271e8a5f7ec0aec3905bb61320c56027b792100ac431f387b269d95f6a1555855d05c5f154e708b25b0b4546a308fee1725a715beb938ccc4bdcee5fe07ce13ebc4ff560aa2f92f43480eecbe9596a57fb76aae07edeab413100a7ecb953d58b61860322add6d28e56076617bdcb06cd608783cd7d24421b95129a9eae1c077d88081c73a2703b3d95a72a4cd4069010d04ad31ae423b0eacb0be605cbd6c60527f34c4e026df6280c0c325a132d1f6e6a479980473afb12836b232421c7ee82a7f118c76eb63f80c9c96c9db5dd8383036ae7b1d6d7084993b003205d75dd876bf7c4616796c45671e32723d6b2a37c711c7000da43f26e2f6885650e4000d2c842b4d28570f9de09b067d939343db7b171490802a03767711409f227d64aef206f80314ae966558ecbbcc4915da8c3525e72dc835ede2b062d16349f7258c5018a3551c0ac0f75fddbd61a4f69f6cced200b3e2564636e4be755f0d16bc0fca76eb204aa9d400af7cc066947e931a10bbabe3ffcaa7eb060ba99e05569789f1643cbb8e650f296b6654ae21a3fd9e58b2e9248f28535872089f2251e992cc6b64dc8ea54e7883f73220ede0da51e49f471bae240f41042c1fe3ea0a4f75fb7c653089440a8b6349e453a3b73ea5ca1dd4da31418f6e202edaebb384d312c1b21eed62779fa5d7ddc1739b52597d3b3e107dd4402c7e2e0fa609f1337715f5e90b2a4982daf6753afad3fb722ab2debeca08ed3c64e6a56c744381e637d6d5be9371ac41eed81fe44c5e953e5be9088f34aa3729fdc369a75f9c3add8557b5f3f5e6c7fa33d68de24f53328c885baceb98a2cb74c238def064e7643b90e539feebaf0b546176836a8f0a59cf5c11a3ebd65229ad82060e918a2cfdcd34a63174a72becece75d9bc5ba405b5037790599ccdb282e6f1d5064c574f2e9c54dbec9381623ae6cf2121151c6715c04c9172b2a582140e802e93ad42b3161c47c98f96c1b438c7819b940e3a86da082fd4d6e8cc239a3e326eb4467476ffefea53ba814c9fd5d6a69344b90179f773ca6983c3c54936351d7b1aa8f6894aaeb94eec83add8b033fea3ac3d678de75be132e3c7a3d5ef17dd70171b62247c7a3525b43e8316eac547195d442e0a789f5c7b5aef5e69e507144b538d26587be181ead4a0b6eb128d679e24424afcbba10a90084a8107195e5acf3563ce0dfaccdc92952cba06dbe8b48a760d29b2ec3e3dde8f4b1056d0abd2cd445c3e492d207344c4963742b192d063f13f77a98cd48f201e4c53162639d392eadf8be9fa8dd5a67dfc45dd7c110fce9b0a09a29672ef3b00391d719d5d09dbcf6ca42d77a2789bf796a8641e8c918eb45c675fac31353d49e5397c0fd400908c3f962bcd6ae60817a928c05809b8d58eba3d813e17588c49a7614be18aa43605afff3e5a8084d3c13fdc6538b4332a43ac722e37a68c463702abababd2e90bc101d94e8f19238642a67f1f9d0afb3e4f78b595c3771d9296535aa87bb14c7027916532d14e95bba483952e81a0847365150cfe64789e961aa2d67b64861e9a327eb3fe0daf7a7479af62f418dc313e970979b03732756b43c1f236f277d60d9717a2dedd0cd382dc7b00ba86f15c6e5ce2a36e57fd6a9b206be25c81ee19901f968224fa07c96e1e60404251e58160c67dbb2bf904db74baafd6137710c2d9de29bd40a84d0e7f811e798109417cecf9a6e504a2f3af331e90ad68293422ae528543ac38fb6657a1c9bdea13eb6b64824f114b018f13ba29f1a37dedb3d9ba6170f458d08ae68fa69c08774585c2c7b16d01a42f4460a901e99ea836cde7a1d8be509c0b9bfa7596db3b57b5653bfb79c71cc757a246c36ef9299d779038658b9d0d82c0a1aeaaa2c03f81199a6dc66ab0cdd5933cd1857e881699d9b911f5041801c720128c3e94eaa07975b06238341cb8034fdebd9461cda7295533524f437c77b03eaebb48397fde5857d09cf0f91c2e2c772f0eb09bc85416033700372070c29d5a9edae14e003c3edde727543685622ffd5fd4f174d275e8c287afc787cf6d3de085f24f61ea6158aceffef8587bdb0e7ae1bdb356072737fd1ae7cee7f8c8dd6d75e6df7887d4c3a77b65d18cbc4bc53b680c1ac68a8013282b329124cdca0fc83d4632247a08bb584d073aee35ff3ce2ac7e9dc92e703fdfa371004123946495a7c13c092bd193d1e4f689317fb8b438e4a0eead3b138d2439d30634627ef07147bb0a0ca4efd8d692e48c3cc702003f3fa6b110d2be1efdf917309a57f27cf726d803b338e1ecc66212f012c2f85ef0f1acbb798bdcf08c8310940731ec10c716f034851ca20d954ef9cd4af922e34d468fab4f3014830fe8be6315900219277281ae125ccbaf751c6629ad4b7a8e33ac1b6dedf748f5b40df45fa1bb2fbb97f5974ea0f117093e69cb443935f1df0288dc35ed28bf594ac91bdeedd89d3aadc1f1743f775ffd7dca07844b3a74c2788cb917dff25a87f052e4d227cb8040633f4d4b003a22be264c2c77988d4c754986f3826ca7c4092bf7ffdf70a9908796b087c2410d51944209002a5adc96db7648716a5fda60cb7f7ce95d15a6c4a84e4096bd5b26c0d2f8c54cfac45a5216aecd3b407206f5ed9b842ffb78291e5c8c44421f256efbf09b11732449725782cdd9341c483b86958fd59c80335e72478234d128c69491a543dd43f831b2aa50768b58d80c63352b00d2e7dcb08cf844a29778c20e08cc48e80b80b0da629123c448e04abb3eee5f7a193ea17a88037521d400adabea35d6970b0ffe460f9b62efd76d3d354a52bc2ccc04a9f8142a2e0d79450061123a791f03b48d71fe30c8a95974aecbd0026973b74a332785c5ef78f617296eee3080298e643152f65003bb3c293004fe635985c3002206c5fb953ec99f1ab50c28c800d8e8ba0e84b369377c5ef03a7b61a2627ff4ec433d396837b72bfbbaad93df8c108b67baf49d844129c076eefd8f5399a35997d9900cd55c12867d25f32056b57f5429208530e26e36ee7179622eabcfbc0788dfc64bd972f960e6fa63a8b5a8f4e1212ae68b7bd2a804ea30fe23da1356ef051e8772929047729515242991a246a8f0b67947b3304cb5e8911b78881020f8c281060cc29184b9493082397fe2ec898ba9c1735823bb9f41407998ff3aa11dc11eef92c9f94a1b28c39b7553bae42daa85507d1b97a7dc6a241deb3d0db2a4a14d2047ea35e28846c5ff46100d179e78e3ed482f9f0bb38ab9e8bac642c46179f87d5724513b96ad4acb4759cdb17ddef770e23dafbeb34dd9f3f9db7aa03ebb9bac5c027e7ef7d78482fc85dbd83d17870f80ffbbf614e5bba0acc61d3e480b849061764e7e9a7234fa0be3fd61420fbd0f3090254d7fb0c025cdd43bd8d062bc5af018bba6c7073a165e61434c715cf070e09634e44e91fbae67193b402acf05d801fe9760f6079e9a677b3c5c4609e1c22bcf7db249dd78dc2d0a51ae214bcc86124bcef4694f7efb1fc0b635384e026f43e314f25c287d64181390b3cd8479f5cc4796f4ab2a540ec516e1d525dc80ddd3e26d238b7288b97e842c2757ba3a54cb7509b18857be82b37182cd1464c7e3eb2df2923e8d3aabe1ed8fe8db0502115fb3748f36aa43c29945f3d30b273aa9e4516b5b3754879d8ab1fe7bd946a97f52d229dd5afd6cab4ddf0c4e66095b17225ec4eabb40d51383fceebde54a7fecc52d07b81389c32db03006148f121c6a5714ae528ea0ff351e4d4e1e8051aee9c80334715397c41f20a03341d817ba17978e010b23419d532ed61ccebc29882c0951f39764e0a539f282805c11949badddc40a67a27679e263f78aa77bbeb8c29fd8c5d43f4be64d2921b9a525b06579fac0c808e06d1aacfc69b10b449e0acbdf1498368f636ad1c075fe534f9ab41f61af86833a3a0b9dca170ff0e7fcb7fa705ccac1a59a0c0c7db9a770ac097d6c72f97a01fe2e36a19eab9ecaaef2b92a08b10bf57c34d0a74731ea05635fbfbaebdbad8be4bfb12c6a3f61fc4f0e1faebcdd8671057835a47db3be8f798492e8a409d908dea1ff370c91723c5d873c45a71234b04b1ada56807956c7e9aa8ccd19bf6f5248dcd8f5f5b2558d388de448da27d5a64c70b541e548a7391a2006c629452c49a847f52c5495ac871e9fda5354c4a25ee73d8bf7af4ba4410ef8d073373ad12f0754240f421fdabab81f14322ad2dd4da197db20e94b2ce055e6693f529ccefd4ac7c2bcc6c7dc00eda0e36b2df93878505d82b8fc67eb62bb77642fc8f115521bfd0d4c58c86d3b68086d62d90e5dbe39a7fd3f54dc06a73640d06d3faedd40c97e3ae142a009fc67b036c4b85ba45787220f7ca83974913a2e235b5a7d844c5bb3cfe0c6a5b0d229a17961e1b5644af351767046c240ab804276a83b2f6083cdbcc80fbf7387b985329d163a6e7b97986df5c483a5f2f28b87c0b42c51188464292d5b4ebd9b8dfc6f6d895be4ae9f98f2b9ccee0a88b36bccce1212f1905bc4637d02c430e8a73fd8db0151c10c2ea552f11ba27a186edc681e2ea0f2cca047c9bf0834040728abe57d01b55155d19b3e15b4ee034df832b524f73ca995e07691db8ad7d0cb9888458bc9a7e76dd8797ad1f5d5a6fcbfb9dae67f313ad36079f2523e8d331f03d7fc994f7a82b07492938ac655f5e46f73f876cd2a2b930d277f2a7890c769a02f1427d875a7e53a93ff55ab6435dadbfd7a0be7df3da75fe01d62a4ca00fcea12b729755b0ba0acc0d9f2b273cd136e4d291274eaa8f9a529c3eef46c78fc496539cc2c42db1b9c91976e9e5bc93eae02067b45bc5d91f3301c13a5b717688300924dde2cb4b5754522584d59cc3e9140fac159625188678f5817cdc268de3813dabc794c5e23da3ada7af9c980937ca822bdc05a59347ddf3980189e7d10228af1e955e296243d6ab439da0e02c4a4b0f584706f456e0dfc14cda3742760e7afb8a144f812dfa123091314ec5325559d7143e45a94c4831e38e05637f58f210dc5982b04dad3f09f6a0c2fa4d11072525ab2b86c8ae815ec71e2a095633eba0af1ed1b69fd9b2f0446b6166118624faf252c9b176ca7f9b453eed8dfdfda6b164bc532b3ea150e9c4e6329c552c0c51b1a6ad890e5c5d0f3938c55eb9554c7eab45457749dea93608b592dc5f4ce505bc3bf1921ae08a837c7754cc9b87323d2af6f672251024a04229bcc11915fda8a07221fe4394bc952cc7a2f3116b473c0d2692ee08babfbe16cbc4f8029e44365c310a421b5e3b06430bfa6554ec6fba8bb0b65aa07145e7ce3a35cf080a99da7e163b7b4855ff056a306f820f565abf5f795aa8f27e9ee1b539fe190486894aa3fd5869989c24dd649dfc13320a7230365ad5bf2b67d7602e99d8d2aba46e55b47f8818107667de6e5e7c2c0e0cc79eab44c5a7d2945fc0fcb7678f691b67d1f66ddf96809803f3d8d428eee6c8470207a037a8a725a04436c45f879ace61ecc0564e8f9b5f213810774eb08dd663811111d606ef3141add19043df82a381c1fcf57f864885f835c9a76ddeea740f81a6ac1cc11fa67c739c6ff686969f1d8886141fe5d646a15f9e9d2876b31499dca3acd0d3a4054b4de9710add988e41ad17c7961d7ac76bc31422ad95a29fc78a55e763c250cf508485ee4a2c03778bac7c7c694aad3f44523ddc89a7dcb905a8e934251c8a83aa20a87002b7c994587bb0220fb29c087ebf88bf9f904a80ac92d1833810e546c0a1fceaa86fea841a8e4b0d63200774bccbdd34fb4bbd884137698aeb2a4361c64cabb47197ca612b36c5bbcf4d124a9cd491e69b17cb957c4b998bbe929cf2d4640dbd778b5089286145512b5460d3adb80ea0df2b07504cd9be6104a1e65ba65badbb9aa40d5e7068f08c65fd68191efd81a131d0ccc8fdd03f81f3d86a0e96e22b62af2c7561cadece80c42ecd11d118206eb3e984ccccd3232bac4fbea94c8023ab81cf28531d362549c2cf59277681afdb16f63ff48654e8d03e137cb875a19eff13710eeca3b4302478cb317df242321f6cdc0afbe04cdde50ac532db4f543c3a51eb452a83c46d164be89e9bea6a374172e7c715a8691a98dd2b50755207ae924067f67674a1aa3e47b5d0ea0b18b9b107f4205eb5cd2025364e9b738d8e4d6eb7004ff72c5b2cdc692d54a222d00db76a5f1a7e5254f82aead2c1e65311e8d7e6d4b6890592cbdf35bc6548181cf859c15b4d746059b2360ade0ac44e9cad8ceab3d184faad9dead37d0c406ebda2d376dabe3f6d3e0ca88d60c24ec4b87133bf06b992c2399e4821f085e9c18e6e42f40321322bce63624dca946d126ca7bcda0820d367782378cf5fe3fc7e3967bd4a9a7349291466f91dd0d4692b151d9165516b1f2a3626477afdd359611bb9db42ef5bf6c90b5d3c1cb0267b0a5224a0dc2b7d129d3292413204655db7cd23f35c1f5dde5b2e6e60fd8ff41c82b14777f34d89ccc19b9d56af147d31ef529f54ed08ed600a1795f0d2632681fec9cc94fb8ec2c7f9662c555512a0e854483f140dae62671967da7c1a39fc5c7c4b7263f11ddcda38891e920f2f938228d1e1e1226ac2f78d92c8f70bb03519d717ee2059d5a917091e4066c958d5702e5bbd2928d3241502fd44c70c9331e059a998a18755443ed505faaf4d335c1358dd4211902653ee461e7f122c9366fa2778cc1d948a68a672a4934d2319a83116adf2624c9a0c43f0a975b4cd0b55df0e0aa907b5852530d89ea0a6a7450778a1a71edaf1286c364fe2a7306d179faee10179680406544d6a3bdfbddce25dd31e0077d86d6887c1cf59b21664619554fb093785634a378f3e9e81d80405e0602d696d5c5853aac31a472f076bedd71f01b840daa49f6d0be511647f6fa0f7d2552bff2cdd68a803c201de934447e55e03c1cd3380a6a19041a0759ba7342d5b3e95df1bf5173ffa3b478a5cb23b1b1a6717ed62e088abea98cc87eb4cdcf5cd63700a126bbcd451f20290a380b5f71be943941d3f9f21930d463c14126b25998423d038efecc865f7e18334bfbf8409462866acf3860a8100ed64ac6397f6412ce332c792f0bd4d1e0e7bfa51f33f1dd62a5d1ac9661ac68eb7934700f2a4ccf4fd4f5ce7d81c196233ee9f106ac3d0d9bc8dd668e8c0df60157a0833f8ab790afab033a18bff45ed00d60f0b6441fef8dea53b76647afd9b181c7258db9e0ecda47d2d7a1ecaa5cded7272bc7be656f2142315a8f6913e5a48edadd8ce23ad231019d099cdee6e087fdd3220e7d033b1cc412561d43827836a52d317b96c00c24fa3e69713a23ae9ab33e96f39bbee8cc749fa4c40356f4c90e04e131a3ebf38e282c383662a2d1b20c00266adab2fb3035042354b5dfdbfafd029addda9222bef9c7418f34bdaec8aba3b6b428491f433f64d8248dbd1741649ca5207b44078c8c29251fe434097bd07d04b9ffda835e389f794d7a637fa4a6b8d149c750868a7193de1a79989be8e940fbe9b9fa60c38c78abf7f815c3f11394303d40a96e6f5bc8afe34eee27d9a975b2614ef29032cc986965184f93a6dc74a26102dfe8e91b48b05f2cbba649734e3c45ab0527346f3a8a92c5ad3df31d8264bfed9f7e21ac1573b98ee5fc26a518232cdb47e4919664ace450a97fb8f5c02862148fcf99e6b7bb93f89e67a0fbedd0442c2d3d3be9b1a378268e42ba9d27b916f75eb9efb5d77f7356697c4646e83dfaa933ec8f31015541411aafbb4b0024fb692766043af8cf9cbd222ed8ddc42a4d72a48823e670889ae1001b84c3e23786906556566670bd2c86bbc53637b68d2921f09e11a074892b0fbd63e890a1825a4a37e7332c2d5eb2a6c747b8472d6ad402b100122202e8176cd4eb6923bc0cd14ab887ac54635a81fe25f438251a4c994022b469a105c127fa4e946b3c72d4292da17bc6814c67ae2f38f70c4d05ad38979538eaad00344cd64a9d224fa75a25fcb333a5af7a2c0c112a0a0e0581baa9496c397b741a2ca2b229e15c662455bc1db67745ce19e44fbf774935e28008455ea0e5b3759e86706fa3fc081f24b0792223f33738b0734327039478db56cc82c34312804aa088662bb642b61e2d13c742bfc4de6601c98aa290486d8964ae57f0b3854903f01d6d3a804c51f7b493cfe88b407ed5bc86fc7f05754b35b1db8724749de3b8a7416be7eb9a34a9eae4b484c0f2fe3b982c5240974fdbe87aca5d792fd36565d0480b0288a93c1f8cf364614b918390ecee8514abf6985118854154fe0faa8c06c3aba33ca5685e7713ae2ef526a75e5231846ab46ad6a4ac348827ab23113e5829fa6172ea60242654f160afa6892fa1d61135a1ceae49a954ef7ce13685877347ce43f44d5f0e2830ff80db608f1f6e444f31189ae6f83a5d2acf6aa53a116b81da2607f7b64e924df49176d4f864e8a44b0ae75a4c92b82777c2b3a8aaa15adf787cccadab688dc75748cb7a2f493f645483a2a96044c2d0c0342d181db2c7b235a4025d76963eaaa6c692c358b9e18d94c27c3fb0d067d720f284fd261ec60deeaf1170375d7a478f2497ea5e8f107b2fad1cdc4e701bd424a0d408e277558afff5241e33536892954b0120bfd769288a73d68851dd3922365c8de3a908d1f59207e8abc98d6375972ea8bee94f920ccf921625f92495ef101f1c49cd9e13e7e688fc38d4cb016e72eb36669ed0db117e7c0814dbfbe9b46bb78848d6e29542d847521c4802dbf3c1b6e91cab527ba0f4f3caa23a5858264ed339ae60510e1c49e5ad01c80afa954df456f265911b166ce624fba18edd8451f20fca9bb005c64034bdfafbdf0ead249a859820313f5212b6f6c652722af8bf170c7d830d23850c5de5a8ebeeb3888f054e58dd1344337298bd10e677b4c9c315ac2c9c40f7819c1a6102393ec7720ab525260e224fa12ce17039189db640022ae40e32aa4615c8c0800791c5e14f1c35c5a847f5448e4160ce3e49d4955816ffee278f516e264e170a9fefdf640435e2527648921d241937589b5170dc26f53bcdab06a997d5f8bbc021fab01aa94e5520f1d15ec28ae20e342049d04633df2e9fdedf4467cb1c36c316de76e01776a01d6cf72d16a508a1cfb5e16ba4ad421aa3cb23c44995345b46474d2a16439abe87ef2d3c0ed0010769ea6b5d598b34608692f1fac2ce21e922a3ccd76183cc78c447c2661cee6a65da4f7ee124ac9151aaac29a1d0f29a00eae1df217c7e0890f7905c4696d35a04891951372229dadd06ebbe09841161f4f750a08e45d273b8096f423be37c1826068af03e9a7aa5f7bf9f3292c6f1f748242d2c31213b37a3c1c34e56021cfa4f091a341052f487bb2a957260845ec661d905cc475a20172ea243284f6d7e95ae1fa9768efa1c481551011529642a3aa6f4dd59b098dc9dc363fefb396610b1c101149590834bfa7e1637ae662ef9b6bd8ca2f02977997a980debe77053d520ab6f0fce16bac5687d1a22f4aed3d9b547be64a97697b4f24b5191596f759326c5f4c2eec3ecd825eaee0e947926443f4b538626b9bb6dd638523968563448cdef3f4d41ecb9f033e7bab110882489d7a38f2bd7d133adb2228250c64e967d809f267d109da0ce7396b9f034c8a06f1a57e8010fc1da0387e1c0adfd5b0612a3a79215234783ed9844ce8ff591306668dffc39e0bebbeea02b2f16c8e99ad5824330dc75c488baa1fb3217cb966b63f26ed6c29906bf41e959de99023ef06f1ff08ff45bfcaa4c247355dcbf5524e1942bdf0c4987a067608794d585c11893277ca4f3554bd7e3d128c501ef8587cd6e69b5ecb69a1638fe916f5f54e55acffcaf58f7eba9e1cf9f57d353e1df484de0bdb2b24d655e86b5ff696d328db24bbf38e4b84b813f18db98bf03577998bbdf75c6813e9a38ff7bf0cb2f4a58c927aa133ec85f21f97f36b69b3d7aa355258416772ffe3551a881004a3692726a8fd40bb7904d4f202675c76037ac9d588a6433c28ad510f321bca40f42c09a5959db9918a81343196a87a034840893e8fbe95f01bfd3cc7afbe14bfcc8bd5754e5f880006374c1ba0d02bab6065cea4ad938069279a1d0f89ca7c72a8a4034c51739ecd450dc134070dfa9fdb8f8c62812ea7070232c613110968765afb28ef57a985a23ba7de57da8a2945266effdb01b8204fac5dd43208c4243afa4e2ce0341828378840d5f10ab2ca1225903652770e684cbcb09c14673993f02daac36284c66d79a10d2a24aeb5afe6d49c8c6e910281cd54dd094e78de1cf45ad10b28ede4264bd963017b409887d8e0613157a48b6410592b0821430539a0432f2fcb92f82b89a2763f49cf830081fafd44409d0a31cc1587ee1930423f889d29b1ab79e1a0dd0b7ba7588a9198903963eb75cab185eaa04809cc622605d7da8174b2b9491c04eac829b737a02282b62385cc88edae0caeb1ce3237fcb3e00a204506ea6a52291d96351fba5798ff5d7b910e5e407addf409b82ac7aa83863044fa960240979be11aced9d1bd14d689843a2336e75405f126b775b8dc25837315487a6e6cc5ba3213bd60535484acb4473c436ee4d6a2bbca32dd7932ae837e5ac08ef2d22e8b80a558219dc643fa18201025877478bb4229dcb421175386f855d1d4837d718e4ab497025cb829f250972665dfa058fa10bdc2fb5fc10be66c0292eba6be805154563b0813e692df92033ade8c86f0ba8ddd4b5d3b23c0d31f766ef510776a5b874b59323457c98d838dadb72ecba017648a9a9075f68866c86ddc3a352eb47c374fc5eb204f0b5851569a6411b0140ba47344cc2da303448820086f57590a973666204a10bfb402a21dfc862f68ffe18284b81474a1385605e67f192fabc30ac8164c3e8153775ee8383ada608a3bb87cd3128520a6ac17ec7454b7013164c515e815f6ca8c28c411d3ccb95c8292dbf9852219ca60e5a3ae49afb929244106e6537e203d953595579e0d193640e6c19b0f9bdb22fba8be65d56212756e0f0025abdc4801d1940fdbaa16e3176810c0951f8fb8285bbd1f0fde80df7caa8a5c4f28ebf960b5a2a55025f9079197cc5d0524afa4be805510567364e6230707576e1a981061e94f7c5e3b41b7e4983beb820f1eff4a81e8f2bacd049710b3bf2833cfb1b81c33261198722438420f261683118ac8e1f7109f5375e880198d64ead6ad1b9e6103f1a6b4bb49772a9a729e64c0a05ed3acaa9b7881ece4cc21f756e80765e322bd1c45b7c95f393b3ff62f985ba77fd0464386d83f874d39e210fa89d421fcfb56486d81651c8f83c4592ffedd5ead2c584faee0584e476ae77ad4c66fded4aa39f46fe26d2768de140c90d146cc5242e5d02e45d73ce3f55d637c802725686ce0a2bdb88b81f7a1c9f050488f4dcf24a9fe979e23780d13c30f3dea1ed3a5143b3a9e2b7e9ce61f117da2b1227ca5e7781f89294ac8ff42964dcfd273ab0a3f59c3f384ba7830c952151e52d14a6b52cfd3c7318a54f8ef3d7431bceab00f3a5b1cc2ca35ff9a0c5ff34d90c451f56f9bab5421cb1481aa77d606f908428f2020160189cbcd110e1d1c7b740be9e6d820f749074713b40f1506e6d0db43441562502315e1d85ee208c044073f2ce229ab0124ca49e418bc371a69cab63bcec25a14eb48cd48faba688efab0657817f547bc3b63d04f6e20dd181b723be9c1d827b8d9d1f13f4b308acac8a4066aedcad144e615b4972e5b3b7437e4eec60f889176bcdc1c7959535501a5f729a9e0e7d52daa79228875ea80171367dfa18a81e4de083090f810c6fbb330342dd72877e53cd6c09efa01d3c1bdfa9e707d93cc1bd006d9b7075d0e4edc953a4ac011b038ac04c82c76ba25a094b29f8a2b1e5ab11c71a95fbee13558894d927eeb71f0d5daec39f074871dedca1c4eec2a6b2a49a304fd0c35ec02358fec58e6badde0d31644e0f8251170a201ed45383120a03d9338a2103f0d799efa7c97c5313d6d867e0dd3b465df6e82b76d44ea7297cd5f4c53698106e3ace0e9ed7b9a150a734fa33453fddfe29af1a479891cc5c763aabff3aad0d9946373516e684ed67ac1df8dbe9aa051a4f452ee16870408946d6f6e993df9942437024e0f3a2d444e260da47214c3ac3d0d5b0f195a60e2b70d4da44d9d66b74db3d2dc43337165d441d294a9cf19e6fc320dcb4b31b5dfeb6afbba1487a48f4614a15901a05692bcb0082bdaf5326e50db3dc9fcdbb11556f756aa0edab3cb3e3c05160fff9c63d1f4d0c46388935e533e0e8c8ffabfa5d50ee6cc7303e6ebe6c9ba07a4e3c43ad7ab71e90500125e2c973e632e5736ee333f5157579e2686aa33c9dc67abe074fa2945ea0923e6fe17a00324cad7b7f08d7a6b183e99945ade638c33b1358f0688d89aa1f7d8de722081109e7125e67ec80473c59a8308e7203a11a76563954a6f41657ba92b8241ea215a670012a9e8bac085685194c20be66b903d64291d21d3b3d87e4536aaec457574ad396ea1a7404e3e3be91000f6cb6190019252eb010774b8ed21148848392ccd968ae067d3e767314c5408ebcb9f1961165c895f6594a1ac0f1fc1541aeebf48270a23f9223fb3c1d72dc1241af678640ff589f7f6b443bd34f06a2b65086d47e6db142e333b64009c1d198c40f11e732917969b4f995774f194145002d69d52047111d4357d2d8349a9db9f927ca4997c042e3aa14db263ba8c0b9b9df9725484fbd685cbb300194a4f14ac38430f54289501fa9caaa74bb4539e0eb2d7bac1ac27fbd65e190c63d8d1588ad28d2b64ef178cf3ffd51aa3c4c16fd83717133900607a2b18d5140a13526ac4ec295fbf96d44981227df7de0c1326e7dff7ab1b4f72c93659e36d5dca06db3cf0b7ca946a5cb970871656d75eb9c20b894a5a84fed3c618357eea781f3e0e7f4174879fcfddd011288f1538350dd95694568b1c1c72f158b878e59c16c6e251749981321b1cf126c1b31b7c7d4f373223bab87ba830024e144932af071876fbb42cc6c73aae2049cbed34ae08888f2ba4508289043093d16f73b9667adafe5b4f7f9dff5685b896338130574e5a67fdb7f7aa6f9b138011a6068a9b9906e155338af34c0e3a84d984dee6e32944b7c4e3f76d226283a2d8f6375818e2f2c851823c01c7e858e5b5338386493bb3dab806268fee5a4683ffb6a813d1b16c4c7b01ddb8902f45548b5933fea5bac789a91e7f65e08941068d97ae626141806308b15f48249b4a4e0486da9cb0e02ec02324dce2ba1e24f98c79988ef2c61382c67b531233f2f357986e2fc31915d94f944aa8cf5d43a66146d2e8cc5cd7cdad92d73d04d6b408e03ba0541da3e8c3a15d6302a087077c3539e64052c4d88ce10a58505798d5d52d9d5e530fda3c8e9cb08979ccedc9eba20a445a49a93a8e4f08342531c3b84526503f820af0ef2c6d34cdaf90b08a4d1522755efdbce3f73c76c83118c585cddcc85596c5145143b469d9fb9d68c2026bc8f0b745a1896f509e6a3d3113e2ec12015824b2755a1200100f2170a43b90d0172edf8a553af736f7bbecb9c83e166666cef722df7db74cbaa50cc52fdf8d21da662ad5a9da7058495710f193fdf8251bfef4d15ffb43f10f311bf1dd6e42794c3cdeb88ab3c5e03f102dbf8566849574baf725a095591e2322b85381fcfdcdb998b919009802a5481d60cff2eb52df9baacc7630b70d33d8dec7688e2750dc78912f0335331b990b4d9c544a74f9c2c7d567885e941ad966dfef976589defff92d91caf7b3d1e11245c47b057de3d0448cbb329f5899871f4ab70edcaf45ffdf99e5f7c90f21329347a335339ae5ef3ce5d0ab12e97cb4a73722bdeae11fd7d21dc9a876948d99fb9150925a0c9e68f017d76dd9f5b309e1e83d40b53c8c372e973a9820c13b648b6ead684cb4decc7ef37776a5135748883ce91c724262e05381e2e6dd18b457d16de81afda47d52f69bd1e35450ba797430f65bd2536de0f6c5f355b9687f8a54def2595922a46796bb33f6f28880564a75a20cf5c36874c2c8cd1414fb2396aba790ba1a826a351892c32adc01e04cc9533c5f2698c873a1fc7210ce84095e8bcb9ea7e42c2f22f34362d585efd426baf9862007d4d269bcc66bfe771675f31d515d9f37b08a09715b3a9b2d003111e6717d38dfffb63ce8544022f00aefbb92a59a5c1ce2814f781895551321c3926b802cacea65fae4cd36580e14198cb37084334f4a5375fc640e50aec170884b3f1fe07795be88ea48c0405dc37b48cce7ef7f16c5f7c1254d6bd4c72f4112b554f4490dff252efbede28fae69cebe88d47d835d74bd060bcf62bbb3d72950a62b20ba379ee57a537d6235b2b36db769d25e6816eb9cd19135b520adc5e7c1a0799e583b9233cb1a27f88e9dd5098f305f862e5a37de12a7e16d2f822720fa2451ca51104023ca14e41cbb689b51173d418e355a620ce1bb0b167843717c7b6bcdc11ab1b45eaa3741962cc174df90f1e60c7ba365cd93044dea27c0f9108242587e1f9848a688510297b7c82b1d33b6950df769f49041db2c4691a61aa55e7ab83cd4c374397244e3f680c30e92f634f7584479f7cbf42f477294c0f85b55127140514122770462c648c698a892243793aaa73f2a13e9769920124e7fc1287b6f6dfc0435d783a1c1147ccbfb470fc4a8d1d97ea98b69b2ed7c096b39114325c0d684ce912172316a2d200aa7f04be4ec3aef812f9dbb30a25e83aa9e42569c047c608ee0308915f3d7dca84fdccfe510ae89b6bd3b46017af884820dbf38b6f1b45a57c85eb02a15c57e5163a901e3347280c07d3a4e73134000c2cb487148d481cea72b80028bf085ca8e73b3623063e114caf9da4145aeeb12968095896501860e975a11580d0eae2a3d5c33989367d458889dc2d28c08b9112fe11001c97380c1eb6fe7a25dba22aead30cfe1adb2ea257389ff7716a8311668d18cb8936d400206d38b05770eaecae52f1b511691f903913b93b050ea2ce3570c0ec4d7f3c5a5bd11b81a46cc718e3ab53f98619bec9dbd1f8288dddd92b4dd63e91a80ce3a8d1f172c7783397b92064d7168d1163554943502e17364e5c6523122353075192e0d6a26cbe5c936620c4d63885103681f28af78c2e6ee1f2b23e42198d7b0b6853273481a9c2733e07f66433e9819d5085f6ec8d02ca76dc795d11d88f97af46eb1b4e5ab245d76bf509ee0a57a92c6e22c9b2b9d38bd3011c8b09336bf566a54652eebbe1e43164d14cd99730914b6704004c67835d5ad39acc8b8055cb763daaaa893cd9a6a2afe49f08f560cdac4946fc203605dac223d48d845f0202ab662d2e4e53406409ba12c58312c7c445f54ea899020a2a0337cb996acb2d58f1223b9b86831c0796354ae2d6e94b9052b662787e1532ad1140559915106546c054e92329a8ebfbe584e5e5efffe114251d306b01974e458057f53242065ce9e82ca9ae7c7d7c1c8d7881aad44457f72d9e8cd698a7c863ff50bdde639ed1dde26bb06c85c1caf065d05364cf254daf4b2cde2dceeafad9834a15c9155c6c6af3947239ba6b038ef7423e55f5a759ee8d678de0cbf49504224c2375189d886030e7f349c343ca323bb28c50900467afb90e288a1521b951298c7f8ca546407176ec78d2021ef956a27161b42b638cabe64153ec248ade2d2c43527c094703865cc019c3e7ed80ac6feb44479ef54e32521b9bec6b3cc19ae818c0e057a286efe92fa8730f6822603f7fc34aa1ee2ae133fdf115550e53ffcb66397d93896816763475c81ef984b39cb596f0d0fd946faebeaebfe50b7912d183114d81671c64160c7bdb56c9c2c851dec100a251320e550d0d83fac62c00ee21bd68adbc9aed05b4ff3b17667362ccddf59a9fa6136a62995bb40f5d183ce6f74cc68b4bb1e46c744942d53295bcc97b5857fa3c6ab828895f45ffaf50505bb106347ce8c4114d59aef64d0c75a4e55b2bcbdb2b285f9caec352ba492fc7dd9dce1ceb944ed7747580d3093964eb3eb81b7582490040405cf6e8d50cfb63de93be8364e8dd4c84f753d3edfb88313bc66d0e3333fd7b4aa8283be0988a129f9ef9128e5ad43e88ce339dc6aea175252193b16a0e16ed3efe9c8d4457ed868a344d4b81f55182de1ae2fbccffb1ebbd32e2e71be599deb95dd9a793bc9cf751aa0375181ce1ae4812298df86393ec97f9381eb4c82b44b7ecbbbab0d4c13ab618cdf78665ebf1099c80a60572c46b4311d05f2e9b38293b6836e1510a008d879be8ba1703236787e001e404eed90171b98f67f8122d7b6729ed1a28dbd15ffbd04444f82fe3e8f0ccfd6f9ecd16bb614fb536477f2fdc0a28835c92369c8f832fb40e520dd03ca06e8ad0c7408032c2269870aa5dbb6cbe4fedb039215f472f755a81ecf5bf2523ed244a9c035e1570312a7aaa6ec4160701cf2724585838d0ecddc2ec1e4b58192e41d7ca1b39e09812b53901e7336679385b96b7ba2dc40e9a22ccdbc4abe83b03fe4a9c914565b0c50d161af6c5a57f6a044597882216bc2e83e43269770b9feca792b979ac3ec20cc74621b568bbca6a34e01cf0984cca21a991a7ff47e5d8f4a1ea9f1b876bc51de9ec45f0d9fc3f63ef3f52cc7c90e8359f7a8d7b5a2edc18654905e70fed2f1548354fe716cc3a638ec8ef9f882e84716b8716b8a6c3dbf88f7651cd3780a90b7d5e62ff826444099a5b88873ccb44fa1c9469f7fc6a04c12669e67729a437e9b4ac6b052d1769479147f90ad72d043fdc0158ae7fed26e606e4fb3fdc07e6852e3b78fcdc8d6a2535105d11cd40552b51d30b676e06eac77337e547fdfa4ce89822c1a56284a420f346ae090b2cee7580c2b7168a7487de4bccecfce36108b61f98c1d8fbedd526e3f9ea9e748abb2009b7abc4080c8bd0b8aa7f840f49f20a3a123ace45decbc0bf655329e574e11d190d71c839f3332b5e48b011ce325ef6b5d6b99e0121c83252e1e04e0f8bed050b0caca00b60a96140f4dd47596aa5166e45a21202c4e1a2efbed5b682c4e4052570bb06a1510bb4f3d3e5866118129bcaf07d1a5f5b207efb7fa11db03c811270f1527ca7b98be3456a8b80764a3cfc42c8aa71a54410f87a91f94f53ea05b0797d4f9eb0e72c17e28f64448e1e57a2598ee42ce4f1adce325e818ac8871209f12ee33dd3a580bf7634daaa5d17f2d7862b8d20f2e571efd8f7f293cc9ce484191cb3f697f309508203e57f8de5800cd2740a810a526a55fdf4c1a8705b157e159578174eaf004886795eb23cf1074981294d5e8bc7567f157c2eceff4e68614e82573455807563b998da043c86fb491555e73fdc1fb67287a19b7550a3ddad8ffc68ed52be5c9728f1546be1d1c74437cba5d4f8a84c48124b458748a93d951f98dc9b4817469889e05d3d9f98df6ed5d2f92d7cc9b743e04bfd3f5d1546d5f72306a2309ac9ceae18b6b288ef4fc016b04db010ddf5276eb4b18fb6daa21a196a93582170b6c9a2e0a982952450ed6c1947f58b0f20ca3594293ba988233d88727a33b3cb062f7d738764a5f26b1f1d351992207e3d720317d90d1218dab71bb09f4615d4aeef548aea0fe7d5f78d20a00a283869af3b3e5de80b6498d82c4f885ff9b9dc63346cc284adb36f7b1216e0bfa1cfd6a10af8a1260cfb1b8172d78fc5e3c5de7c31cc5c312dd1ffaeaa0883ce6088fb4cc54c75e968a38011a040486169f05507508e3663873f482827f546d9330479fce0b0c755d79c92110e8e0a5ae5c71e683be1a764300652c65b1abf55c143c5f2f13c0bbddd9bdc27302222321db0892e72bb0f78327c7846afde8aae3d11ed60214c3ded0baaddd6e9b3c0ca1450582287070cc24feb51fbff72cbefcd7275ac10ce65b718998368adbbfd0ad0d27e9636bfd900c1e38803dec96ddbc3aa308ab5d6c36cb4b618fa576c6e568b198f82dd8345018ae26dc82cda4d33cffe49cfc83d13c54d9c740fb8503e49c8b4a7ec7241006abdb4e45778a963d87fa6648af7c5819a10d99684decd6fb0251c572f61a20668402f909a48df034273cc015ee6722376899b73c49825858ca0383613de9120fa57b6493c1ff2063f2297e7ecce74cf7fe5f552ac456159370064cd7adf1e08b0166a4448e01b0027859984f0d8900a7a686222a6540c0da5fa317523e6a6364cc5ae5862492f72ddbbb25155ea2e8d3e4570102910cc1650c8f1f4d50993a2874c30ae94380208be581215f34be4d65e8e86393e08c8265b0ca907e7b56ac1d299a76a1b08449a11b6a994dd6092ad972a68567d84efab0be1fc019b86b5eaec4af9a4a2999673f66253d76ad9303e7aa16940ec7c9a8fd6449cb26c4ba45598b015140b8fbdc46914df7277bacbced9df6fc1e8e4a939126708efdf78b2313d1a76018cea3a49dd68269ba3d052f55e9b7112b68c039eb1270fa3a74752a3357044105aa44872a026bbee6dd7df29e71e55d65fca643908d51de13e542352f386fbf7ec735d9ecdde8239907fea50116173c35e4ffc22cf36151d2c5f2a4d2c23354fabe760b53800a7c3062aebc37fa348a2dff9698b6408322656f3542f8afcdb1fae95aa005a70af1794ab151c834d58c781fd4c4da5492bb459eee66be7b84cfd2d4a68833ee80ea6b4d26c77224c157c8ee8630dfc17bdc353b6dfdf54d204e8d7b9dd24aab972974972e0f7222f1865d9fdcda00110c7bec7fac372534382049f171cb7727fa595ae6be7b7e05736f1302acb3d55d8154edcb2ab76efbb2523becf575d30bc5efc984600a00842b0354ef5147f1d4fcc3a84cc564070fc3248914203604ff1cc3a5ebd91ccf95ff3f546d104e0089e8e8cfc038010b0bc3c3b052b78301e7ebade9f440451194e5c8780c62ce4b6b4a31ca238ec405265afb71179c284030ef9d07569a002a5c5943faa2f4d152217b30d44b5fca2863356dfc40549af674141c4930920b424da9a131e03fa62cd0aaa9e46b606f2afb44658091e68f6f7305f0cf4e904b82d6aef2329159a38b22469bd2edc688a180a4c8f1c247cf73c20d464ace5369b2e39dbf9cbad6f85f01ed63dec1e1ef1b424fcee92ee79fa53ad0261c114a7a8cb117c3051887e8951183853da5ee425c14e74f54c290364b37bd9a37e858ce717d00ebcdda3c799232f119ca13113272980f3d0aaeeaf98d0918b0493ae2b04211ce4ff9f68b35236f545b1dfb31b2b3bd4e833db6def808b1c3de9ca62033a1a5d64d4adf398c087230fce496c0755f8553a27a48a430a65cc2b58aa4d5406b76c66588dd6077f8048c0c4879719904fa85491f47e51c73ad6820660a9f29a3417b7c7c12d777f121758c624083ead289e54b36002bbdb899b1cc6571b0671799405f0b4d9c6e6b40c5dd540dba73c5a45118fc16fc2ecdb16eaed4b9a2682c29888b74dad3e66cfc188eefe038dc60d0489819319ee216634e6c5956a4388ab8a8680b5af7481190c0bb50b941830cac9e8a474ebba6358cd6de9a41b16b9cfdbd11d308d61b7e28321df110448f766a52784f51ca0a52d12df66bf8372fa3473e710e5fe080c34e71767348a06836b521c23bc93a66d5ef962981550c638735831ab21715322c85b0cf7d690dd4a179cef2ae7876abaa037c371eab0a12259950372e34d772650e44db57833fd497dc402eb8cf70eb7da136c11999a1468bbe6c8af9488a620bde758944f0887257b3c72ab317a6590d46a80fbdda4a999617a46e6dc2bc0297b3992ac09cd6f23d587839c30de64c7600f2954debe3cde0195d71baabced2f4f45209912a9e63a235a1dca768ef8ad35ae65d9b2e2c9d73553991ac9d4ee340d81bab4b71ca8367603b94a1c21ab47444b6f652b79d8273a615f37c0f64d763852b9c4611ac726132e2250dd1e112052801582bbad973fc5191b228b475c5bfd1bee725b0e50af91eeec8d88b6071fb738c820c49ff5ff032a676bdab184ddb452eaa247e89b2d78ecbf9e37bf002a2730fdd4f2813aa8a3339454d900575adb98a88c937b603c203041929668590021842e1767a26b4ce11ab64a947fa1bac18b292e8002ddbe5b04ea0f8072b1f127c86d1ace472634d92821169288f5dcae76a46df1b09f2ce5e56e0e7107e00fec13ec5b93c20975c395fdcffb2331471e544e4b36f06bcdc840b74903e909711232411bf812fe013658100dc492474c346a83a760ed564e85eeeee8545321daa94041e466991a8589c16941f4506aab90e99c5c8de4bb7032e363250961cbd034db9ddcb522284294d10e7c1409bc78f18037c8d1dbc1dc337c1149cc8480153e2135d9d51fc6391743d069d0b3c71d6c193b336c92965d1a0f0706d09abd76e295ec90f6418cb9ebed2943ea3054fba6ed6d66dc4693adf5c886c88d4435c6027bd2c3278ff96089f25b448783a1d8ce15d87dddd0c7715d0d71d4dbc80d8cd795ae22a404d14ce8ed6cb27c69122897667342c3069da779749da6aa347a817ef57b0d5d1d04e7677a293940a81209fd71279fb4dbc1ba85e8e9a407a8c44837289669f909fc42fdc654134a7b9385ee014a30a75476ca34775e01f5515236a55ff11850399589c3adf0e1aa351e88dfe76c855433ff379c322f65823899588c6c20dab9eb3f5c1fdc7121567f331a5088ca47838549b6b43754e231f82e46dfad5b9b3b59440c40dbfe525f7931a28497f6cab7d100bdecf43b6a632075c40fe2ab01c6b18c7e24a3c2b94bbcdfe5c31f2540e91cdc072cb8a1eb9fa022f5198bc6797a8892841dd6b19730f9d46f68977b290490ee830f5fee20646212f2f554d142dd2d01ffedc52b085352022ef8652e71ecbe946d4882282496ac985b97903907e90a765b9e0e53d5a73be6e345922f01ab75c204219ea143bd8a3d4c15a2f1691e98bdabe3d91bdd6224066ea717937d182590e83fdc885380d55085a308899bbf0688e4bdf0b670bfc9c14cdfc2f42b93acbdd20900a2848a85c287f30a659cd70537e8c18020747b9716fdc2bd48c412876b083c621300bd2bd933f5c676d324b750617a2b56b161a0fa673d7a2cd9335675a622e8f7d705e6a957b50852f61ba97be6fc0219712fdaf3f386d93f65801cdb9c957ae5018a9cc52dadd7ebde1d7f7b46b0303e806d09b237a359f33a563b7000625fc57e8b1bd166adf4719ec5da47c4295ef16913229cffc40ae5c0b3517981dd2fdbcd6a7ae07a1aca98ed42399f8cbe4ec2562e1608ce2f6cec6bab3d613ef6a30d28bc5c73e66a669474c58df777c544edf63a8912fcb17d5d07432984bc903843fb0d2ed6a76a053ab67bd36a9e688ab374d88592ce206719de33b5109de540b74002ac2db7e1aa31076f312e2658b73b8e5674eba7b08639d92c80591b39798a5888611178dc1d6046c2162034a99cb7a5ab830716498df656dcbb6a2573681208bd3002fc80bdc5ebe298b2b73f469739bd97eb8990c7780b3274a64540ac1ec80f060134d61d0323242d1b85e46cc505ffb9890bda971a7bbd8d987745fe9c720e9637dfc2753a51b235ec72d36a72603b1fda6778a69fef203cbad3af7ac88ac65e686e8007bd70fa3f2b30c4565b970ad26e4ce40959b98042126c2fb37ac07d98015a4768ad48c81d7ce52285fd217d684bef1daf501c7138b10f09459c24e13c54f2c802e883d8ea72a440224fbbb2378ea0d875d750fe85fdf08726d5c59a929907e23514311846f7d4111f7d3036586dc3952e842182ee45fa5332c8e127f338b8e1f0d1820a698fa7170c474917e246a4a2e639a9aea28981470a169223c45b2c7858990958788e7bf4eef2c574516d57efd2e86b80058bc8cefc751a65efaf6b610092e7c7e7523c2ffcbd6b026d8c7500bad449f872e8036efc4dce68aef73573ecd0e182e4ebaf566eb0197ed60d2bfddb42cc0f857c0128ff59ca5e73b9ad9d91be7f5d3c40600c793adf8bda7edc4cbd7034b35506cfe47dcf67e470cf6b7192daf9000344cb3472808f34e3b368706b2ab4d0248c9af70760e18c1bcdd85bea785b1e23c15e0c7a3d3037073cf5853e900223e4752a8b442343b8095ed86db7d45bb63859c0d4004eb43ea9e98c7aeb8bf6f36512fc639193f962d77ffc3a9da5a7b9dfea76d573585fb9f37e222d453f3c1520320b65c175851acc77538774df4e156131ec287306a32e9a285ce4671bc3a330b71d18e6f24b65c69dbf62e05d2170a3fe5118fb7eb42109ab61b1abd85274bcc19ea4789242c045da8999164f3be1e65406e5870086efcab7a81858fd7df721662f7b77527fe009457ebd2e31140f9f5cce007b7cf979b01d86c4f7e9d26fb4452f002e729b740a0139ada08e4efae7ba571b77210188e3972ebf4e3bb987f7e7af57b1b857ee70fed7a8c446bff3787f2e9fe86aa4f7bcaf4608481e650809490703f1bdeeb3b63d88d482a57d97fe6e3fb02835a71b45723865a164079167fde7834f906e34f14d08ff13a40b78079ab6f713c0c1dfbd90e0756dc052d873804d303bae52e2ec557606fbe7a1489b57912f02f479b52c5db6363bdd749be91c651dabf095de100653a7e65f24ed345d7e2ca322063f206160224fa032b9481637211b49bc1adad6d71d6ab4e23572ab2554ade509dde629fa81b70eb4fc60e363cd55f05b7a25a302fdddc79ae30a2bff836a0770751a3f95c49357097237646648f262f5defc4775c9ae8c9f846b7d989bf3d115a7a87bba9de483f9f704914b1c1738f08b1afc06d2d38237d0524381b97a3250f220579e81d54ea2d989d1f91250173344d2d62f9732923f4244b63ba7fe77a581d29981dd8191e16bd063bced31ff449f53ffb5a1723a3e176f449b88de3ce083cc6ba4cfb731fe2d09dc95fb2b9d0f40b0b563c14d486b26812ac88197a919b9f5b6f7c75f512d50a059a2817ddde0db9f3ea85d679b4f7925800d0ce30cd036dd0efd9cc9d3fdc415f370eda67f491c6df98483f3fed8d86c9bf85cc6b28dd00eb6c48aca7fdaab30c230af5382620c963d441e9a8b35ec9d53fefb4a58871e097bee0f539149bcfb76437033d911cc634454cde1711a1c790874dc621f73b066ca8c80a32806439f84b0702f2483bce74d80bc75161eac2c5b2c150bc874bd5985e2e4026d18d628e40e5ed2af8662634d6447c5084264a5b8503c515934e36f4607083df28a07a088468f2e9f4d66541c205d01c8074a6b6566a04701725b6902938f35d4262ac57b97861b875966395b5e3f44f45652b8bc237cf79ecc7f76508d008ac581b9fb356e66bbc29d814043ad55cbbdf91281b93e1cc798b2847815c1408e61094793ff44f4650cc2f92f983c0f6606648a0727841d3411b31fef5d1864bbe473475c50ea7eb8f6ae81137abe93a751186598a4a63f9cbad5d534045cc7ee6095e801c2266472700fa8f56aed4c40cd78cdf97b192f9546085fddaffdef3b22d488cdae91025135375c7b990d45bc00fa01ea5f0b6c2535c54f3987bcbe8b0fd76559043c05342474058b5561501d8b498cdc94d5a5700e261a0ee6ce54290a8acb2bf4df46a1c0c36c9015d63e8b201aec66d0d6fae06841fbf8ecfe0189bc11a5b3a8c95b91b070c1a8f90327ea48d3751265e58ce79ec7b8304d806433c4996883bc21b4279473c86ea1c7b636ac7c9e0e1f38779e5d43f549e16f8786d458b1c62f6925fda1b193dc91695bc6b84ef0025b5726b79b66f7460e919988a2acb8ac5db2f59bc5f5c5f443227a37e82a2bbf54965ba524a26d0739332da09c30e639a784e0f4c371e72a2974dcd7f88ebe4dacbb4e35599a6470d3a08d41ab6f8ff217fb39c6a3b1b12d3e21e4472ff26b67f8b6ac97eeba1d954dfc26abf6880c102ab2b8836615a970b79e5a9fb76906039eb58f8d544321d3b44015df2943720bcb15461d2e8156ebe77b6f0256c7d26cdae2d9499f07362d5393613de2b1a539005ae0eac952bffe3bea93da8e1763f7c9040f68e5d77c1f5c74d0a37904e38cc6a67c541e5c6c4f638a096a0264bde08c6bb33c80fda9522223c10535f60420f698584542913cb40017d849074ffe1abc1938f143be73958034010b6d8352008bce7818605eed9036b85c6f5ef51d4a8d4d8b414e8c27ada29cb8b09c467f306f7c85528776ec093b96308534804ba7f0ecc3de3a79c0dd7052578b7d9d1ac7881300e51b85ce7404394390d801eb7337a379806bd61b0419e86d6b41eded56c0977fa4fd513aebb56cb393f956bf1266beac3fbe661f96ef4594f331155b81bd926c301b7095a0dd68530d2868faadd388dd30969e322b5295937c7d41866b50c074ea1029eecffd671fdb9354d746465261b268a24b53d61019c7a816fb465473021270fd26e12e2f310417053401c82e9e7eaed62caae6c01b9255e8617d820507978ed1bf220165e91cc02a6f22cc2013a1860eba352636a11360cf0f5b208505c50af876c9b8be1e0d1f8f8466de73588bae80597200060cac3f7fccaf02f40eff3ce05615b2b4a3061eeaa38c4b7a91299404ce82846455e18f39c315def08b4cb69f482586426a7c9892d10577a820fb8c1439ce3c645853528c03e0e8c5022417194954e46a47b1d13dca6039add0a94572094b24a07cad73b9b679f6fbad34030c24831a2cdcef7814839beb92cf5e04213e21097445058d021a2e7d142d5f057ade155c93446d775e514123dfce431354f41ad54aebc401aa81ab72fffde7bcbbda59452ca2403b5083109770911c9b62728c3fc24322a1a760eeec44a49046d3e7d2f4188ef9919e64c9a493c1e1825a04e9ae6e8b4e90f893bab192290fb9446309bd25fcd3077aa96d1263e8d97b18ac13c43b4a18f42d14f9a5c0d737bbc893bf28c3efdc706b9fcecd8a4b7da9aab7d4a8a37f46e4fb2d7dada7ec83e278684ec9fc37196ab68abad110d1fb21300861f2b7c0fd97ff3c9fe38093ebb3007df55d7259e7813b38b81bbfe48c171b01a6fe2e464b7f1b0ed90fd7dc49b986d18b9e93031d06e3dd9cba8986e1ac763e7064acede30aa67d921de6871cc2d876779428323fb27a152ebc2dac675327926cfccfcc09064deb09bd49050b9cf4e312b744a9ff1bccbc2c6759d4cb6c1e28d9dd25dca6cda113423ccac34994ecbdbbd580465381edb638be094334f6c31079d32d2c764f51d3c74ecd8ac12d91fa3d8ecf127ec70140c269480a1aea5f95155744aedc9e55a11b275e1b16bb31ad49642b9675161aabad1bc4d6942d492b9fc841ea8bcf1b034345b4a55b35513e809d8e421bf845ab11d19ecde2bb3c384cde9c4729c8054bfb8a009d195ebf3e0786a3d81e3a9f66ba51a9b28c81eee034be1da8a7d5a0df7dd6f60b7bd6c92ab4dfbaa0700001b30359339c6de5a558c373586a965e9b64d2ec9d5f69a14dadb5338b2630e0c916cb83e120c39abbf7fadbdd66a9a7e912b8624bab6fd3af33f4016f40a28d8f458f95021851454f0b1ea6183c20a9a05f0c7dff0c84ec0312107009b2a00340248b9807aa1049d1d3b3a60c831800f8817648600b90006e80e10430c5bad7bdb1a0b23204b00c673855819ea0c74c85480a461010cf8c1c20a362b1552b8e9c00d06187272562b6badb563b23f76af86d5aa250a9a1b9a10a4478cc2d603dca16789c275382366d915dcd58747d9854eb6b5d6c7f6139d2a92e8b4edf7e078ec57abad8f2cab2964f186aa30572f692325574b53d854d8e4cf95b4f11542273bc61b3b43aac2567790abad66819236aeb991bd7eed92fdab37edca82f4387dc356b83fa6fdfb58b4472e466da41b0b1c8fd56e365aef636f1fbb8fd570ff0856abfdfa3f381e5b6f680b38399b1c22dbaff684aab98d8f1e28d0ec4fca78cf1283d80fe79c732a510d91d9f365f6d00ae82fa17ba847a55b1b8bea2891c891e3a3ae67adb5563ae5ac5e2bad5e69ad745aa323a28c74772925a5d43a59fbe3b4fd6b124eee73cc7cda31a2b0338c908911e5ee52ca39e713a59466db64adfc8a44531bf9de1ac83172cca63fd9d8f29b90c42cf2251325228752684b1d528a448ed9d2ba7b49223b134c30a186a645202020243223a24ca0ecbf714252d831b62494bc41d1b4988fd0ee52ca2857b5566bedbdb736815d0cc334ea2552ccdd7f4e8ec729a5b5566a2990b52c68aa4b50a0588dc814c3b02214d1c0e390000e491c8e6d02271b078fc37d0538781c14f09edfd959413e127f3a710b16913d2cfa110c730871a0dbbe6a88076daba70e73c82cfaa17dd510bcad4e22b3ab1ea24ef68c13f49e3dc1242579a1d444a794524ecf22a5ac938bf52a699c314ecf2269757b291c746673d289cd39e79c93d249e7a474da39e99c73ce49e7a473ce39e9a473d21f66889a73ce49279d93d2e973529c03cd29ceea9c95de5b2bbdd5d63ae79cb3528acd0cc719e3dc3a8d8839e79c94ce3967fde75173969993ce492776e9a473d2e971153f9cb3ce49e7a4b587ec3f7dce39e7bd64c40aa566f54345847edc45640f6b7bcd0eb13fad46b7aa5b188bbe8c439bd69e82b58225d8f6b3fb617c1cb31833ec5a01ec18f590cad25741a53a74caa76ead7dfb34c638443591fa56df105955c76963e4002caaa5a4758c5a6badf4a9feacb5ca1d683e99aa8f764ae79c53ca9f71ce2c6a1039c49c2b227b58f82d38847e6c612cfc3262b55eace7c73053b02986614796c84df5b72347830abbea2115d45a6b9cd36bfcb0d65ae39cb4d65ae39cfa297583b6f6741bc3c9b4e74bfb51aea27db7d1e51140d42718a594d2da03ad94e6c8f1cdba43fe814a4a292a5382e6cfa14e27a864e6f3cbbc7c6d7bfb4932ec6bdc31ea285182036adf4f32e1e8d94a92dc377a7af6126cdf5f82daf743267b6317b44e70c0b6fd7b7f3e86836ac8d7efed63d82fd138e48d6918e48aba2057b4c74aaee8cf9bc4eaa125f6ab1eaa7f3ffbdf3e834952b0e76b58e65330a18b654952b0f34ff0c8f6f3b5fa7dfac87d2c739de4e23035f6193cb2646eecfd3770c9dc19fd475ae5fcebd0a794d20b86ae6409b6ed7335fc9e41ea604675d3d7eccedbfdb8afce3bbfadbf6510060b2659c51b4aed91a1560e4bfbb893c47833a4fd50eb599aee215faee8f6f62b06aaf26f1be853b650dd340b2ab176fb6ccb66b48cc661eaec311087b93d9b41ea64f67fd34f80d499d8cae821ecc45630b49f61d67ebef5d65b333b9368150df6ebd7b71ad7619c8ef1e6ce2d72f4e28c28f4bd60ead994e66cea420fb9a29fc4625653fa981eea740f6943f510a7a9b4a1bf811a1865f8180c7f531badfcb0d65aeb9c33d9d0762a19e85332a14cc34025188661f6ef7d1ce6be3a4c72b7cb90e4d69f4f73904e6cf5ba50592d9d314e0965c7b732ca8e5fa5941d5f4a1f36c6bc91c6120c4a9bfe971516d4152b98503ce2503c8a4b719f39e798fc068a031f238d547fc194725cdaf1134000940b3bfed891f68836f1a90e2946e7d4a6b4b4d2f85bceeb9b125a6db55aad56abd56ab55aad56abd56ab55aad56abd56ab55aad56abd56ab55aad18658c1255428c324629a59c5407cdf1793359a6e3360d67d8b5954ee9349d9329659c8894464a63d4219356fd21fb5324f3e9e911a4945246f7a85d4a2965a09152caaa83742969a45eb4ebdaf7e96beeeeee98bb7bde3ba4a60ea8cdddddeb0e8b613a76886118e63976e8ee5e77700ab4dddd9dfef890e567de038661984fc6300cc3ea0edbe6693709cf681b9d4f1789879cb7adea50799071e732467b329c84b510c3300c0c5121edc2e9748f78c8f27188611826b3d51d304d66da3699b66379a34f1a76f7b26ff32ceeee588ecdb37816cf72e9b6619ffd86c11db29f5b939bcb2d647242b0df99c56088dabe63a346c8f25dcec73e2a1b6a1ee78da83e47f5382ad537a97120b99aaf023d68a8b6bc0a568553e1e47ce46afee67d54ff384e587163bae671be48cde3682645f499dce8264545529ff34d70fe3eced76895535d44f5355fa399bc6e92d22a8bf346eee3e0bc11d4e77ccea33e47abfc23abe6555ae5dac784f7c1799af739e17dc0f7a9f9941396b7047e3fe017346de683e067f421e1b4d0020846164eca63f25e5670447c7c72bee67d705ef534349fc2c951d5d4d6565bd8c5037b581cd1fbbaaf2c2943aa2d571833894c44f5610b113f281148dc56e89390c4a4eccf280a56922b2df92802c13fdf1551e7be803c48f5719c39836cc56e1ada4cec307135bfd22628f6fc9ad8f3b52dc336fd1dc59b30fa62da4a8db10bbbae5c79c156b9c8fee17d5dd9ee2b02c17b3efd21df473d56f7d79a3b9dcb3586a9f68a5df6498bcd919eb8c87487f689069b835809bf30d39e5fb9c8d2b1dca37d8fe68ecabeea22cd1d95d52a1b525ff346685ea59be43ccdd7e8264545729e86e69bf8f89456d98facd4475692a7c08985e3d1dec10f4ade8e85e3f99e7c2d2c36aa8405e7b87db7effa86c802c06b2d3ccefbdc7c8fb75a8535111f5ae539ba854f7d91163e85a39b1415011fe79ba0f039dfc2bb2e72f3a94f69263d7413f071fe268bcd41d9da91e351d990fa9a2f92fa1acda4c83e1314b4ca3fe7efa7deea2235af351350dfcf7923a8c7799c477dcdc720b51cb0c7e380287c0ba0fe1b10fc1f600acf02e8e35700576f03aaf091230200ede3b37a9f14dea7c7ebf751e17d7cbc0f0a0f7e0c32078c2c1c30b25a0023eb068cac1f6064b10046d60a6064d95c2ca046a1878f145458adc0c852018cac14c0c8f20146560f30b25000234b5fa47b94211d71447cfe799cf026a4be86e6551f8304c1c802bf1fa03d6d52e009471fd29eff60d206238b07185927809165420d1859aaeea53bd7d70abd235796cde73eca0323bf0f2e896f7f1c3477320c0b0a4ae13b8a37f3af1437287342654e9953d517e8fed00fefefd03bdaf3c30c69236548195286e46931df3ba24104e261117534140e32187b7a5d6cb1f9169b0af7156fe66b958b3cf7d79a36758b1c5921769920c49428413dac0b46167661d97b5ff577e485c1b2e77f5744a06933df68cf8f687ead2c19ebfa830466cf33f67cdbadb1e77b93f52035e2f84f544d76dab467587db68f78e3af612b57185b6010b40506405992e0b3a54eccf2c61b1b48ea7c526c50a17a5a7062ddaf5aa0b41db720fde051dfb922104fe92294becfa4842356ea234724a573a6cd94ab59831caee68e5bb460c30727c477ce285d147ead6cc72d5714fdb0431862744a5df7922fcc2c327e9f224cfbced5bda44e44edb8250b974db7185bd41656816a945a94c3fbe2a262497d4ce9ceb5703744d6bd60c5227b2f6fc96bf25e5e1a7bb6f67d5d307187e6539fa15e7efcda9a3b34fa828936f353990eef19184ac768237578d7d0b78d3dbfb525285b4d5630ec5e7327b2baa6dd39edf97aed89691583628c9104aa4b96f08ace356d26b7ed60170dba6c26a75c9dab5ef15549edf06bcd845f6b0c4c297bab44c6263732fc0698acd5ab261f679f285ff0e12d12d40de48371e73e76cd9dab3b57885d323bec5c32db3bd7dcf99e449bf9f32be2b5e7d79921046fd75feb2867e167830d0795f0f1c6bb703c58088c4d0718753cdd25c455095d38064cf7428bdc0d4e9a30d2410849702922c30c5694363a3e0758820eb79de375801ae85e381eed6740df31cc1d20926d5728d2667e0ef00bc723f39af62375347d5fc7635267e675e810c9b6b597794d03eb4f4b9bd1a163e6e7ebd03868e6fd0b6e08b6673e86198394d1f1716b0cc8da1f40d321a343ab68c831826dcf682ca4a97fe122165732e1b665b48fab99f72fdafb178e01737b8f85b49fd1f33318e34a46e3a0cebf682c2457f3391ebcf9171c56a1c8d5fc8d47eada6aca210ebac14138080b794c14f41c0c8ec7b5f79a41cede7ee88d21f70b8c4442ae32c85f6390b16b4f2f62c6d8767f50be965c7d3f1e948465879d6bcfef5c73e77e506403b0ed602c9827f1664ab9c3090839fc82f6dcdfcffe5af166ba6b9aa63d2657da7fad08246e0d2b62895604e27beed831667f2fd82ec84b94e1af79980db5afe4f06bed68dac186d4c13f6bb0e9877a875f6bcfff9eccff5a1188fc590515455e62cfaf883d5f8b7132cd34aed55b3e0b3f6e5ac0c901400004e0c20b516707860100a131c149cec19d507a95e862324929e56492abe8ee4868996269472fc678da5e76cc0205cace3950427b0e61d9532f91fb04a81d96a0a7a7672f41ed18725b7ef805e1228efc7026723bcaecf8b1823893ee2a432b77dcd77e7d595f7a95744e2a311d73d8ff448b3d2a952c1dab6cb02fdfc894afbd91f9dbcbd7369510df34ee18a4ca1fb33650c5d24095730067f727116cdadc97f7ef631a0372756f74925256f178b5586bad31c0000305820d19cbfe9c73e6ac56d65afba89884aafa8867354aad48ae0b03fa912b272c4d8b1c0f058bccb79a499e350546dbdfb9212c298718d18c48aecbff48fd98c676214a83e44a3ea5b4566a944424759cc8a8821855518a11499dbae5635698b67cec85a52177a8117645eac42db0786df9415ab67c2c694b6984850f7688b9b6dcc20a313bc49668750a923a21264548ea3851b6dda869d6b9cd41df35282bd56ccfeeda4646d7b5b51ddb045545e6d4f266397fcddb2c4703c5a4489d10fbd9f2b378e347eaf84b2bb6fceb8a4066b6ff55927749eee4db2475e4768f3b1851b4f1a7d1a88851ab32413b723650caf1549acd5a776c5b1d9a5363449e963c6b4cc2b08a55cc2b18623c988394a8568c0823aaf56e70d80aca70fedae56ec858961ac995a44860189390683c2f321272488d6252925188bdb3b89e4c7f8b23d36751f0ce97468382321e72488d82b67c6a34c10d8ecbf154aa9a52a552a9a84715eea6572d264777ef91002dea689a6b3ae70ed99d2ea1bb6223f0a74df5117f2a9aaa88df1059d2b5aa88bf7d7bc314f4b85615b12a6ab5aa88fded37cdc48f10071211cb6a557dfb4e58b18704b1c8923fb18b65198681aa21f7f1e38b61f766d8d5e1928d7d04a346b2fdb499ef60be21b256d366a2a64d0443e8c90f2bb2fcc3dc09c18b132bb2e8cc81a62a22738836f801ab4845c33ca21a12dff6eca855db89d4aa2259a699f81b4098c2c5cae18522379258454b3610c9b6ef8739e08f570d998f3da6c34f326d0d3df6b4db9e3a5cb2ed0777bb0e5196563b3bed2b27646e4db7b2d7fcc452ab1d6665f84e8dc61faef0a1dea1f7a241b991ca5e0f5018dea1f7dab95abb8ea6431c147e2d1cf443a63accbacce4d0be4f91d4de11927c4146e11d35c955d59916b99abf7143a456cd1e9f1e1f7248399e1caf78836545c49ef843991ff6447571ecd91501bf216de6fb605072149426e535a19577f2b352271762fcfc4e4c8c385e6d6746ecd0883a19feb00bc29eaf4d608bb9fe04381e6b7bc83502544b96c01633f712f05e021c8ff7e517e259e492f0ccbc10a7b13e39c7f77a99e73eac3348e8be82ee6bdffbba4c738dfb9ad9757b4b4c52a76a8fbdebc71a78c45f723c1e18f997d4ad698f5f82d83b86698f49aea687460ebd57565b33ddab5bdaf2e3bc317bbe4cf7b467e7e2411a3848025cbd92adf65e5c60cbb24f51f616e0e8772fe98f5f4aef5c748b8c737034608e0677e7c0e69c0cf5b597a0d51cbf05f11dbadf29c99d7bc10f8ab4999d6bee50d6d7ba4cf725579e560d91aa0924575280beadede8a5d583972f93873c7f6614b9fad9f3cb1772871c76aef9c5176e75b01af6b5b09d21f520c72e6c206ddf9993d40933a43073f22a5dd82072d786c2f68e22ce7c8d669a9155d8c78de56c8113ca6ccd3372f8b5bed6dcb9af7c5f616dc9237258eb5fb1da6361dd8e7558b3dd6a49f785992ac0dd1059d815478ebbc802db6c410e3b17c67064df9293c177ce57637bdbd14bcb894db77fd8b9bad8dfb1e3162cb2d8dcf6020349c880170dbc91eb06be700009d976e00b0f1c21df0fd8000446080118e1d31117922288208c111081046294600849c65032c6044a4b847002327070235714dc20056da800072b706201ea7bc41d9f89d4e5891d7734c915d0d78a37609a042187329c0021d79e303afc20df1d967860c327073df8c0071dfcd08396194fd600822988262867082166881d10a1c60f1a45f0c088348e48230a0f904023093594d801909825cec89589a62698a4ace18419f989fa06b8df03287410e4832872d00236a45812fac1943054803054065110aa8099c2898a9795368a7050851b56dcc048082e20e3056360a07465081e034e06bc3bd71859065be7ba7253bdd8bc30de2baee66b325066f0ccf733de5d52aaf26d962049df9f3a768991efeb32e578efbd9f2962028d68839fbde3b770a3afcadffd2744b3162277963b88a6d1fcefe8c322777c38271868913bddcf17052877b42809467016c76329e8023743b415c45e82333bb40c9ac662e07866023083916c9b8b2dad2db7d401923a718b15a13dbf53923a91087b3e56923a53b27cc85d637b5e0c1c4f8e00b8106e51533e27b4aa7edce192bab92fe1c30f8912dc8be6d266481e44eacc29ba8ef106cb320c3fb6bf4d41957fdce244133b6e71a2b52fe8a3b16e6d4111e23e3e602c1e6e1c71c4c12ab21f0120dfe6e064a0db6a9adc716ba17d6924cbaffa487dba8fd4ef5cdd6b88ccc9aa87d41f211e460e6b4bcaeacadcebd02af9f4c6d39e8ff493b4e5c63c0c057af90246c677c72d5ac860df1dbdfc00c617216c80b19e21b6f8051136c058cfcf16b1462bf6a547dc417dfc1f2804a9f6c983544d9b5c6a29512016c2563c088e024b116fe687b4077bbe1b8183e2cdfcfa45a6466cde831cb7e02269fb165c201971c1c8d2b263940d0929ff804e2e23999f1fa9f338c3aed7577f7e8899b612b9bf27f1a67ead7853b55f270fcc7d79affbf25ed763f29abcd711db115bfd22d71d7a47496c314bac845d2ff9c2fc1944c6fe6b7d4adfeb5bfa59aa216faa79aa0ebf9fed49703644d6d79a36525fa6972bc17d4fe2cd0eb612df2e6fee64b8cdfbd01bc2dda5f65e1e93dc79d67cef25e4829808c4417245eb0b6122f982f7921e537dfc54caa650364927b91ad346963ac65518bd184214db39b0b3ce9575b8fd805e8ae881e6240427d438437305d1650b27cd486651c61a9b0eb51f2989a4cecfd7649c302ce7f98a37de8b0db99a4f9d68935cd52fd815f43bc4447b7ef552bdc861e63484c895de75aecc291200f5f3b336e24e9625da4cd4cccc0e33a70c29439a3b289d2585b565c125e4125b06cac87ca6fdc85a6bad124492e38bf265493aee6057b4998fad9003b01dc8f60753db67b667dbdfa3eb1049d482c12c2943c29dd679d731b1d5a46cb712aa84a7bae6048b6fee252e811be2af3d2a7f3646aee66b66ef3559de470ebbe2cdcc9eb44f7134b856c97f07e278b44a838c5fb8d62eaf975c2d61d70bbb9a76886dff4e7b1d9009d7197d0f0c33a8c477135b4dca738738080749d93290bee4eacb802192e89425491dac693a44c2e90c09cc92bac8fe5ab2242e39cc90549249aed298944be23e8ddc4bde36b6c2d1802b166add06f4878cc5e85cd8d5e5a00365dc68e7c2ae273614d829499b6913764b1ea40b23e2cc9f63c49bf9a1dc343c493c8e94f7fa9a80e28927381e1ce44150401145f4283414cddf3792fad45fdda4a8084a7f13956b1591fba86fc2a4c8084a3749fdfdab55de84e6515fe43eeafd519a49916692f3a86782f3f79db0222bb2689424a1c177cd2be1a94fa4e62397b25f4b69cf97dfeb9ba8fc693ef5f78da05ea59bd07cea8da8bee6555ff3a8b728f0fbb9382a9a9a140abfbc97f7cae28d09d1c9298c0be69ec1c3350ed8c632ef1b8a40866a7efea744dc41fdfc0f0a9eec5d46e9b3ebdce8ba2e4cdcc1aece09e7a0097768f02491dec7e87376da4b0dca8d5dd855e3b5a592f567eea8a44a55f3a857d5c813a444924912690ac7535334526097141b55ca2176b910c7934425ff89a854f2849a8f9c4afbf8dcbc0f8ff731e171dee7dfa785f7013f27c9fdd4fba09ee6ad56494de404ed8455a3fa22f755a9bfefba088ae651b24241812abfa0ca6940953fea232b05aafcef479696037e3f382068420b3cfe86d5420e112645456a3ef54ceeab744a33417d8d16630b3c06c6010e835d1e2443425d2634a64c9932c5a950a1e244d18990907c0c2cc59e9f8a3a3828aee67bafdaaa2daffe744c4aecf9ba736dc9be7d8abcecc30f88cc8d1d44d4a1ff1d113d48e6e438f3f260cfa7cec920b796e9cb19a79c9db699eccf5d3fe464acd4c61b9aa35c6da03f0ae436aa0aa12a361a30b2349c51784d43c3e3514fc383864504024caeafb99f7a23a8af417d0a85fa26387f2f086293136d2990c7145b0ae4a179952d05f2f8c8f1a452291e9ffa263935388fc3e33ecde7bc119c4f7dea7168bec87d1e1f5945504ff3a8a7d12aab55346f04e779e82645348fa3993c939a1c23341230c375d4c3a2d14c54a99cc761d5d4a4e2b4c9c9c14141fbc81ead53aacf7923349fd24d524ff3393439df8426b2583dde52f5f46cef357754fe391ed3dc51b90e9d2b06495bc600497289416b4f2e31e8719c7d72046202dfb6cad29e4a31cb5cb404ede9455a809c0172c7ecee7a6d8c1bf84e6d89e13a1d10bc53c3751076af29ba579e92bb97eb2b497bde6be50a9267a7f9fb5a5d26b99a3f60928f6aca34ba28f557c78e5bb0d821d392245f989fcab4c89d67591e474bdeebf57a7d3f5fab8b6322b90ac2476ce430739a3e70d72268473522172d7ea4c7c69e5fa9d8221571452457f39d8aa873bdc41591d4b94972757f7a90d7c82176d5e0ca9e351092b6e9fe88c96e9fe60e5d23dacca76dd0278ab70a7e50e2cd2744b4918284b46ae4fbf7a76ada14638c403053963b8755e41af7481fdf216d22030739c1850c21a7020745209c10cb831cdefbe1d7923a594605e1a06963d3c8e13dc2227590a48e778469ef057a69c895d724b5c784460ebf56164fd4e0b4ed0ecec8a1f7ca9c300c8583e68e7706d11a7b7e1b7b4e706a9b83b5d6aa71dbc6f1709c7ccfa863d2344dd3f747ae3cca8e2203edd5fcaec855907d8ac28b9424a9f32df119fd609972b6c38f6e3868ee441691d1c647de2bdebc3825b864a1b4ebfd896a70c9e28b77347768ae7784f28ebca3cf7bdd9fc9d5e0316dca84850b70bd223b0d7ed8df8e5e9e80d93f94c6759833ec38fe15dca26881192d9042075208e54068cad2142a61a80c95314404a60552bc72e8bdb0172685036a6b69fc88f28d3b26bc6c482184834cf3d8bf5c1896330af5bf5ae9c033237a458840f07b62e20eeabd20084db941eab529b545e5bec8c835afea894eadf8f4d303d40a3b57644a35491d185e39ae3026a160c839dfb141654829138d91b52a62e4b0bb81d24eeaa716a41363b12b67fb6bc5d404ae52205efd70baa0ea480aa130b2d01457cefe4ea1024696217a2f6ba986a90cd920e31f22fa226b4f89aa7cc943f7c3fbb261ccb862bcbf68642e546a6d348c659990a3f67ccbe5e31196b0d3729c297fc61b75e86b2f8ff8678f8991b3b8e510d10d732dd09e5ba4edc27ac95849aa3476d94fcadadbd7bc4aa41603dade929786e7bd2210e9bdbcabd5560daa40b5a5c4bf27df12338bfc5be3250ccb19bb783018a6339a365ec369cfaa4405a2065189a847d4a10ac5a6a26eb6cb136f8ac27a71add52a1556a2ed92c3af95e5bae3961ab4911571811457f3aba8506a943d3f1b535b78572d5a2d39b32d8adfe2b738c83bc25e1a4919bfa5943eb55b06fa764ef3c0c86f317e0fc484e4cef596bcd7efda3a23dacc5f036b63cf37c29e7fc5bcae19178d5b841b849d0921738aabf91268cfb75d582ed885da9243eff571f9e1caf62d759028171f266bbe77f449a95178e0b45623d79ad592a5b51ac59a962c39cd391ab277fbe4383303b14f55c31bc709c1ac96ec1c7e09d68fda03a36615cc1ee37832ed794b58d532afb6e4aa1a552f7000014415d8765f66604b75b42088a1d5dece557598c33e6991e921c0930b4e3f50984ee9ba8e4ac745a632b4c51051965cdfade33852ae567b7f8dca9016997b7f9e7893445403a22a5954b94bf735c57d610963b30d7b1dcfbec518638cf11418632a3016d97bec372aacd020d3d71ebf95aeeb8aba2b7251154755583103231964ecb3c701a63a5a17844e4ccd401f76fb6b5b0adb1f5bfdc819c21813e118e4fbc29d0fb49ddb85d105a10b837aa22a5772ea372c843057ccf541dcb99f7d10ece72dc24563cfa73ba84faa32050c32ea65887be83ef6e1d7f220d17142ba75e041f0b7a6a0e205597b9a6118e538e10adb9f6eded6637b9c3b1774d676c1c8aa32859529a8700115568cb295222b7251155564550d4d0a756b308c26e7140af5efb222de60638bb21546568c5c4045be2f59dad3770116ff829dd2143668668a171c6d7981d1f753df9bffea8ca238127587d845848f0b5e0003bf5283a8adb89aefa4f6b80e778b942759f1fb6b43e436c44627c2076a3cb1c4644e2b19367b44ae41949f142d648dd2c3e61ddd32e2ced59f94a42f7ec8f168dacc0fbbc94596b92c016649ae2693ad9225a884977093d4f129f67ccc4604e252eab80ec7e3ee25cbecc8450a0c84705bd4d67dd59616b9a16eb443dabbea6746a9740d188c466ba8bbe242011d958edb33fc5a5180acbd5fc1c8523ebdf174b5efd0b77cea23573db4478b1d54b43582e884b42914b99a3488a2e5a480ad734520b2fa16a85b5b77e9de34f6fcdaf22017cc0d5381d8f3b505483071e77bf2b51ab0cd24366ba7c4cf684fcc44a443fc4279115b5cc183a01e56d8b9b6ac52ab6890716d7f19d776add29a261b4dbbdb714b161d4829b4553f8a4096f8ee64360c6bef60984e5f191d6239675abfa6c3d50abfb0cb4a91eb87d8a5a505d9d6b7ef73b35164fb36284f19b5e852765b0355f4b5772157d35329db9772daff7ebe965cd5d7a8935c8da142ae9e4abeb77817506c3feef609e9bd3c7f2d2f4cc4e212c37276ad64cd92ad66b2af7d68ffbe2e93bfb59749ea583ded65baafbb745dc620a5ebae73719189b14ee4fa0e625bf3e8eeee31c9dd5329d7bf3b5a29998bebcec5c325c5dd3df7dee797f9ed679e95a35aac933511753428a20e9522ea60df7d39ce7c0f92451cd7b6ff37036e32d9e31c753522db45dd3288703cf68974f126e86b9f3da679ac0bc3e29aefc18516cb44ee5c3e1863733b7a6995b1b5784b5cbeb961170e2362977497ba93129cd99adce80f19f5291f72902bd686ee6b748c8cefd5f04bfa120c314e88c5af85beef12dd17ebfb923eda4bd0db9afe88e2cd9497e9e5f3f6259877e484f8d76f499dfaf669d07e2ab9c44c97fcbaa59e4bf7355f51b5e3162c43cc34e48a690b1d2273e94288fc054d9b2e92e893dca5e2ced78a36f33f22b0d2d2768d5d1a76494e06bcb16b89ecbf61ab7559dadea58b50e4b140f932bd6488ea1199d21f4a915cd717e553222f499d78bf1febfe7b7ed1d99ff755b3e98e5e5a5df814f9d77250e66bd922748025decc77b0dbf6392152cf2fdc4c4aea8293c85a9090f6fc8bea5cf2821f14d417657f4fbe20e28d187bfe6691c8daeb8945ae8ee46abe8d92e757ad868dc81159dab039e711f5f72fea9db092c8d99e5feb50eaad1119957af996e391d58b0c7ab6c730ce233f28dfbc2257d3c8d65bf52d22cbcfc6481da9eb8f74b0b67ef2fdb012d988c032972eeeeb89ec96086ac4010ef07700c753b50370943ddf019cbfcf9e31c8cbb49b32fec12db99a1868cfc73f76882c44a66fa164fa9a0d22d70f3320b2bf4afb2deb6c8c5c65493a7b43674e0fc03b34522b046ad522709db21ddea7096014d8eeeb32adc2973acc4f72a1e3a8146dd645452c999a1100100080005315000020100c08c5c21171202a82f5011400106f864a6a563a9286035110a3288aa220a3142184004000328a9019a2a90202646a851d4b22eb3345b17a5caec43f58d3e69d11aa5b30c35bd2d8d9034db3147f496f4bf87a70872cd044e5c2931bd9f5899bf02a3aa17739cf4d09fb9984172595d631f860745db10448950a4adefa8a774819a948fe89190a005eb4fe20c671079938ae56325d27bfcae446a9770ebdc810d16b199b2dd9e3cb5629df56263d30267f8cc5aa67350867daa91554b9a7f91eb9cc5310d991d8ca51efccfe9a28b4e77d46b2c9ff0e6fa8bd0bf08d570e24b800529e30f9c57693f9bba9482469db57e72b79aa9fd1c9dd89f2e6aabf700f206279088f724e40776cba7a5841a3a88be57c3bd1a3a0ed2894f3c84e2453f4c1580527013cc64b01598fc25df5a982e206d2107a759ca1d081007b8e68c0c09d0576753ddc43113c35d52c1937ddfc37924055c38d82c47bb243c4f246db43338f09d019fb4a65c76d54c3c63cad7c5be1f5ec13d852c4b674d1c1265e41e9166ce99a888e45810d0b3a1759508171a5a9447800ba07167286da3c1bed3e1daadc2af6dc38eb64481ad247cdcdc28712d1ebea015fb465bbe35f7ef1ee9c7199139e69a8a029567f5888f244c03ac3dc5e3cb9ce0dced9248ca3bca407624329144cd70642e4872b1784ed7f0eea419045e977f12901faef49209b974e09bb7a2ba32206746429eb12a3e89e64056db3509ab334aea6cf82a5ec9411982954aa2a57f3e979687620927baa07e9e8fda18e9b5dcb733bc5726cbe1709d3d3374f3658171785d9aa41d110c4c06b9cc0ad169a31693157466872fe48218f1dfc6b701f4d11ba83b1119ba94776bb87485c077222374c1373d6a59f4747ece7111751c8a85d22371c44265a34520ae910d682e8061c7d5f2d715df2e8fe30e81edadf7c4c7562cb8c26a5c19b613590551a0aa81a8b159dab6fff3915dfcb80ed1f8a3a0fb61187bc5bb2790e5e0a9731d99162387180dff9f179014ee6fc433f20595f7a46cab243609f941e20c6ca94058311be302194c0691afa15ca1030d9b8d77c1e0982d161a85d049d0e7dbad63c5a054fb17a74e6b6274eab23c6f5b29720e24d22ed0b30a30c98b1a194d28eb5f6f7c456845640ec05e7d135f42ca9e871eed3b51a7313f57f38924cadacb8d27beb3f542d942d6fc793398b4bda003da068b8987b60db0e18b35ee52cf6edb0a11e62ec69328ac24b44a3792a24fb76da6bd295838c8696dfa99e0d6143ea049cf4f0e9a6f3500819b1da43e6294ac04f0fea011fcc650df8f8d11c2526d5392d731988dc0e500ffd640450b2b0aaaa3f231ef7b73030d9c5de429a0ade50b031ba02a667ea7f9c82f75c84b5f3fb9b37952983014077021bf704b8dd61b6dffe0a9c48be7e3c57fdd64c20d7f404aa162780d8969e855f9140c58c3d55b66201dc9c5eee4250698944b819088d48f1e2cc5e6ae8a3f6aa40c6fad1bb2aa3db2459e7aaca034a4e6a60927f5989abe3202fb05c4a2d55e62d8fd33a247d4ebd494f10279dca7cae916194bd1fa619863f84b221f99c8de112067f3433807ac9d6eacae9f2123d1146bf82d5270e28818013002c11992bff8a0e87fba14a33fbc31bacd14575975b273103edc73168d8a3fcdca94f8e79a667975eba3203f976f548639f7e079d6465a2f8bb3ead73d7ee07d6a9bff783d5a1737790df665ac5405cc99b9ceb05757ca4129cb2293d7544b7c08eae218f7c6be0853af1f06639487940bb021ee6b616a12edf4b42b96cc478f70e47ce41cc89045221fa4d97b95cc1e77939371766d0ce8f0377dafba5e75a0b5633372d933afa340e560be7e0354f0259f1589d4cfd6533d481292cb6d34b53041e153c8efa64fe9bcfaa54c8e6619eefd87b740348652f8bcf7da064fd0dbff4f00b40824ea1c931e6ae5b80ef6ebfe99ebeddb34ed797c9253bc128a9ffbbf748997abf9a99106e7ec1909eb4cf9e15b0c6efa41c0f165b516c6a1c1a6c818d36a58a8b618c355978d5b2f6f30f1976f55766d47e86f5c58d96538e574cfdf94e24b8cb0bd78a393ae6d75b33057d241a4706b5f0cf4a21b2797cec72ccb0d5e50e8fc16aa6bbc70a7774106322c4917dec959161e613fcd50cde7213975492159fbceee2b352c9d45140ff3ffe700c89ebe819a9c39a9f169672cf4300ba58a6f3da4c8297d62d1ef38b724fe0ba84a1082a2090784e53ef73bb81381ff14fb2c9b81f1b0f07c1e37901a6877a2a858f7b9fa64b489d9559773c77591ba3e88f86b496efaaddb0835c8455ce305e29893a852225b04b8bdcbc98d830b0fe13f010cdc0e31f841cac50114ae59776577a7ac7f42777c778d1edacfec9603103e8ed20dd4863dd29c38c3e5872ec508cd74999eccea8ab31ecc768c7f45676117b9abb477fe5162bb9be7b7a9a64554b9fdb48ae4e2e3dc88c8cb111427021cd70876a27cf0af7e1ef453a9c5b6ddfc563659aeb55564fa3981d1c28d15e3788e8b1419943a13393002b8064d9773a5d9104394b44c7db123585cd0a5596f66ad8db544c0a07a647ddcd0f5515f2b9e3cd3843a1e44119df8168005b6b21e83d5e32bd43a329163ad9bd68eb0bd81820b9df9e7b88f739db3f405bfab514d037d70ede83a7522c33fb93692e14dbddab079c514130442f3f114bfb71c14bb9fa9e903a2b013289aa54706e0db94fbd2ee39e718c6062301ca66c12196013262e69e0131ac24517f8461f983610df5b545b812abb0e1314bf720ea1d903fe0267bd5c2128fccc5c6adbc3fd5799ddf2d29b1c33e3e0012e88170175d1c94a3ed103559598491de0db57e3472159b3d18dcbb48cd654d99c041fd821d97e94d9835c468890cea09619d8669311277afcdf83f3c1664f426064eda0d19a7e4211fb639d24090139ed06c173ef68c78e5be2685694f29114701f1407b18e397c584796b0d3616eed85f177f209b2b8f91af74b4198171b439bac12d676ab0bfca07347fbd9fc1047308db52f306a7fe0b6139129f87e72fe0d4d848ac2c285dee94e9447e60c764c24b21a5b4ee512b306df00da498a05f69d5d7ce03417e5c0d07ddbd7ff3daa9b41d9ef16653822f62b8687dbd496d5d664cf61cd0d501ae2629e95a5aad8746bf7a77e6d15bb3633f3c682e9bac88a8b1443eba79f6f82970608eb5d2b866f4899a1c0b0688ccb166d38b8fe707e13e9dcdde290b2f15bde7829cb6dc5d104337efe9ea0c320fd2e0855288b3fc698044aae568594e3ac1bc145ba08defaff5a8f10826828598ab4f191a3e711a64902cb5769625d7c5d12aed3088eabc7ab4a52a486da100d496644e8db6670fb6dc1bf19dbcf9e291dd4d4cdea8101e82236225abd091eb14198374fc5c665ddc63e993c1ea99a8b4ea06916673359b23f1add085fe6040d81fd32a137725c2bbf17a3d4d5dac263430adfa2a161d6dd8c1467829263079e13c42c96e173f13e6e0a39996107bab0e350b2a9349551d206b1b5dfb2da12e676e62216a3aaeb022e8a44f866ea518b242bccab4d3dafe9b8511632c85b2e3e414c8661030ee88f445a17efdd72cf3cf9b03818829f43e4d668485912bffa22d8ef46e47b4ddc712a245a395cfa75711a96a7c4ec3a99d7a23ad2b72dd0b9e07e71f3791c3fcb57d07c53f4a095cd9702b55142f140cb2bd7eae1e6c409d45133d961e0c7d998c57f9f4651a51fea159ad207fac0a4c9794dfac88b883d828c6c752b07a3d838635ec52925ec01a3d150dc99ecc3610889c43eeba006a30de39a5702d0fa496e71915b7ab16c86470fcefd8a9d0f2d7713a0e2a8f04abaeb8c0d0383dedaf68c23f91291ce9993e384a32aa4a3766fa48dee1e6471d96bc0cf60fe5580cbbcc23fe7bd747c93c08529289a14d2a1962944edeefcbec31edfc02e802b3bab7217a049b54ef9d8397530565ff3b559ba906a71b5fd7481d5ddafc6db7175545b268983d47926fc75d301e90dd0e2f861218d2c56ed7d06f7eacc92383c286b27bca03680cf64d8a7c2204645d2afd8e13e04476f5e034dc6082f2fae93740ae8d10fe838a636afed76b6d8d0ccab97f8c417a23c99a003be207dda95c1c8aea15c04d6cd6ef3564fde8c61c05c7d7edce4fd892bbe80882dd3bc9b74b2ab665cb8c556ecd370a2dda547295617d911107d69fc6a96cadc549617ccd8377e6711fb82abc49009e42330e1dc9f8845f63ea27bf1b9946f75b8f078f3bb9ee02ef93144ea49054e86df37d7733fa2bef9d6985ca0f231151c7cf748ede949719b78ef70f10e5b52aa4c02ffd93417e943029fda433291de20e4426b9ac2d2ec9c4ab9cf87ccc35689885b998f70dd3680573e8489ff43957bf492e7272c8566fcf844ddcefdc185b03a75582968ac773f9cb61a696753871d20097fc8139761b1040a9f57a0822b89a6f11974dc96d5363f4f4751ef2f839b1f24954ed345752cbe755d00e533b46764bd84bc519dbb732c441ff940079c26d5a7cb189f56e0e81c88609528621e1cb95ebd3ff717e53415a6819f1369eee016e4fa2ae0df31049bdff3b193e80e189be1f3804ae4f160412e7c5f78d9a7904765331ff57b5725dfd92cb51682e7521ca4a250effe8d22874374c023e80680e9f1c7f69dc8a21b732ca656072a7179b51dc1540bf2f5f60b16f0b28e48b83d1cdfc764a7b724230bcbdafca4694897c3137899f039fcf22b8601f6c530a4ccbbd1cc0a0c18db6c4635283f27e9f98f28ccd01b17c360f11cce817de9c84ca22365e4ab346ce614277d4486c215753eda6104db863075cacd611da0236e1a38bcf69ffb1975f4f7820f5dd6f9fff73e22b30e34befbb9465947a589e7268c59d78466d576a2a5624ee2ba290c7072b42041db6275e3d33f3f8118d39bc1dfbcb71ef62404fba09b6a528a2c6446a6d6df79b7553f5f3366b03cfc1498a79f827de4fff5993a86dbbd4fb2d0ab33232db32c20ecd0eeb4c001e37918a3da6fabbe570217dac736e58b752445a1da275220723b8e6288805b1ef9ce010fbce57557f7e1a10cb280120054d64760823c81efccf39f2100f70a2fd675440eb437a0b5e8d38da5b0259168f417d102ad1105b9f22725c58e1e26eab87cc967a368a384a5d0bc13ae2b0bd8321c71a2997500e1e7f1b297c32cb9cce263e0b74064e257e9b81bc7b7d4a7f0bda0a7fa6a41ecc6f3d58c09f57066444134f106c19254f3c645e6ffcd57f841318fbe006e7b0c494ee2bf1096ed65908ff5e6286ae1e6e94f906843d2007a2b253e18f906010f962a2ad89b2676a270580d503ae57a53fa58cf97c8fc2b486cc8a8432ea30dcccbb775ce6fde00fa495c524118f679c68ef17ff1e45ea6889aa5d5f2583ccf10e170e48f9328485e6a7bef5c9554e1daaf08d9c9c4b7c4cc1c099cb3c4ce16311bbd7ee18570e210512350931bb64ac429e53ac7b66897ec4b354ddf744d24a394e15595f3b5668d832787c6ee395374a8f704295f0b87fd75b11734b6b3b256119503d2f9f5e705230eb49bd53c66221fdabd8feebfde23195e07357d442f496adacb5e6b8786c737fd96875bbeff28e6a9e860f1172e7b13e06c9cec3b61401d059bc3f9605e3330fb405e053ed4a53776643caca012484075c0b062cd29d2437072804462057d3b4ca9720104bcf2cf67336c689084d4992fbdd6f7f3c38151a5907aab93a95d6520139e3309f5f03d3385ea56a7cbda509efa9063d6ec90323b9393c17d41e1852ddb01d5eb062e7e6590c75db382cfab29f0c1a7ef1d09c7c8d229577a811c5e0604087b31b6d3c61e6d58cb42873b16bb78edf576a3ba675bbe039b3a93d0c231781f0a40c40a4a69c49f0b81163f17e4d9f392e30435b2b235686a94343cf1531d4a4e6e25034efeed219fc27b45a51b77a7c974b99c4e8c16df14814e8c3b1e2e7b42ee292d8eacb120f29e5db386f9e472014c1b39745181c937dc7753f0a77649595a867c0101fbac96a4c8913f7fd2e3311e2d23c4d638d6cc29f8828e695045e1e7483baad427162f6156314025e4e0ee678bb87af7a66bf05b0f4c024aa2741b0b688b7595b1b3cab46acefc1ef791e81c5b65e5f0c81c6a0ac10a0d539ec25de0a1e540c4a4ada318c7577700b64906afe7c2ee210df8e86d507a1d954030babebd008b0d5636a1f70b0b0e95afb2c740487ff2e2137f2800642625387fc89a3962b613655ed0586c43bf5acbc4ad984091628200ad04bf93399d49b58cf587cd28c453a0b1e3db6394404c1061e2a5821995cacc1185de1045083f94f57f4ea588aa823d0c8ac60f836d5813426e28f8b4129f50e7ffe232c6042b816a0ef279f13b6d59d6f0a9009b9c0f5249a654d37fc16872395a7516b46e13fd4d6a1267f88b96fadb45d0a5a669bf9615e01a18dd4b0687445e96237e0e05f3981b883c97277a4371b4adf98e39be3e9144939642fec2f2814393e694a30eed9c47a853d0bbc261e707aac00040f4bec9c8879805d959902c4809b8ec5970a8ec1bd31a5a8fd149d45cdfeb138995eb4d215d0e04f1442f52566d3eed024396a5f5aab2dc4435fb0d06e233ca8460cc2901a09b5fe71337d7c8a0895431491d95b6a741465f1e1bb29ebf9dc3d99ab9595954ccf3462d4d63bf6fa3918579c6edc466c90ccfed614fce3353809658a6253d0d03fa441758897fd50c493445d20651dfa030611abbbf021f545d6c67a450799372c74e325b772dcda6f7cd847b67509f5edbc8538795832b6760be3bbecb9fa72fadafd0c8869c5f58fd88cf367d7d102b89585aca544d3d586598118b3ab0af4adb181ec9bd7d46c52674a772b64ccc12b59107ece7af06e25f37cd7295d232f7db64f28335aaf0fe7d95c374375166b04bcb4d6f80c0f062e6932ff1fa1ed0a66220b4937ae652169f2289ef19acb84026e70a210e60f3816b7b9cf44f14c2f0a4f26486c1776489be9beabf4ad3c91c3a53ec73d69130fbf12dabbe605d1d30654c2f23c0af4646cc74485ebff865e701e6df1efca10cec7262af963d8bc8b80d191738a2f128ee868b1253aac36134decb9b4cd5a7e848de2e621d4d5bf4d53aaccc7afd127b7fb38d674bd336a254529580eb62f625b3aae471083ca49d4a42de76b960e35e3b69b7e88373449cb273a0fdd1f3bc7c56366b779d41899b3ddc024aef4e2844e0046fcd77889009fad397d42e0a5c64821620b4befa17e3630bf95e2223ebdecad872236206f7f2e80b0e1348fc5ed5db20772248b09f688ee66d1acb9038e6bd5844c15d214a73ede2d47f3e4abb1ee54f3902e8e72abd8c5920a0efd0aa522ecd621d3e04f4241c803685089b0aaa032d570854139cac8ee8fab0cb4e1750150e47a2b6c695f1832a1a87dbae36ac8eb6d00e1912de9bcb5430fbc9fe05564c6adc32f3d505b015f594573e550ce51de7196beef0960378140aa818fbf6fbbce123bba0a7af01eb93946ce6b01f09757c98ce9e176bd65f723aac353a3666fdf6f3871c24c1663ed7cca60c3b9d0da712938c28f84c37f3a981fd02b91ff63ab3d726c093b5910d04e951ec2380377d80159c4b33b3ca78d9c27eb7d71d0f2d3d7b0a3dd86ca881fc3764a19fc3d34b527d617938a9a7e03f7143b986ab500a91b14b0c18a8de14b31a1c5ae36e85e34862f2f3ef97a86df5bded41ed3a920e5e2560b3ec21ba404e1b4542e292c72d2a9df5731ff165a84b6b1dc9fa87755c7682d812538407642332c64361abca5c6434f7f70ce4e6b51ee894615c2eff2d5528c864f450fcf76edb0cdeb242a6318900f3b87f0609aa0ea52e1bd530f2c06a16fe9d17eede1b1a976ade08bc4288223c54588ddbe33452db81ec4ed76748b8c0bf52fd6d9791dcd44737d4ee16fccd591ec36f443d52be7529a0f51cbb7e7f17bbcc7261b981d2bc343ff46d9c71db9d4581a77c39fb129911bfe61e81364611439e3bcbdef94ee9cc5dd0c4b014464d59f19771c399dfa76cfb6e9a113ca4efc63ebd8f6b4b60bfaaa710c46a667048453b578c0b2d1fc6fc1bc8a286f1254191d953eb30aeccbfda6c56665a2d9f171bf4b4098b6a1af892be768c66140e3e8b3fd240ef1cf9b95b8f84759930b7d8eb75b43fbcf61e8febb40b33e5a20011f6914063bc3bab8f7e5ef6b7703366ee931a5b0c11a4071647185f67df26c60605dbc30c2f1daee4a0f7ef1cb566eceaa415de13dea6a4efce4803900fd0076055a095899524de9c2af94b31e275e699846535a28537a3c06aa7e78584a24f860eabe0e7a636c48ad7cf0b97a46d2c7bfc37b1bee7632ed1f3ae2c2dfe0e45e2fa3370909698a02a685ee27aaced9e00d777ce79591fce7b5af6db88906c612fd7358cc3d1c101a10b9930bdf93366534d08587dc9e1b55e523dc260df37cbd9396ac2df41b8ef1024202a168016254fc20d777a306ac6a06eba9499524ac9b6a4585ab24e58999047c7e4c859b8b91019df7e4ce912277c2a70497198e84d2fd25386821634b92c0be8e1a725ce6628cf7c912e64c9d72fb2c7a967998dec4762a97d22fe1180ac6bf8e4a7766db5ac6a8918b0d8bd511ce3f9344641ffa004f2b14869bd08f6eca853654ed62ce998a9a632f88fefd82818dc0be06fc7fa4e08883023843059d968de2ea1f3819bd98d39bc50db318c8c3b069ac6b6a67cc5b21102427e886517d219c2d2f5c6457e135d2dc11074293110436826212619d6b02ab87463b03c26590a0b033b31828b6d4f45f4e4b0d4bd6b66732dd5366618c69a65be84c5b3d6f9b243a0f4666d22ff49d349f8baf5fb4ae5c336e3ee2d68cbbaca32112fc04ca31f60d9f1e1573c31a4673f5af0274c0c1a66ebea2b83a0e1693e2a85430a62aa126f320dc7fb3b75e0910180f494fb49beb5c8bb7262f015127f21778e20d007329b02385428dd1d25ce28418cbe5fb471ec4f9f3ded306d268efb2fd1362dcb85cbb0454c877a2d259375b4ceeb67746a17db194b19834206347238def795eea0f680738a38cb1b01e896a1721a0e844dfb0a7e318cf8c962b817ebb149877cc127ceb147e8575cc48f567e828d345b9445f70d25d05c0ac77ff76e908a56ca1b77eb56a333216f050a148c4ce5e28c5bc8114d29c2e87f9b2c2534d9cc0dc03ec335874e5e54f92efd3a824b7f9236b62a096e257eae336463a978019fafbb6653c1846dbb5ba6c091ff449afd4d194fdebf44a3c2b8844ea3650bfc39c61186113087ba6d4d7d7881129b8322bb74cc31f7eb7d84e780d7cad957e88fd222312be8b35f8161dceba4b6ed3cd017fc1452dcc98f7e131774dec2ba95039b7b55a99e6c148e8fcd756bd059ab33fa89e65b7790c685d6b91ca20a8bef606efaf9814bdef72d0d081d6e6a5a4968f9139796d181fdb44d30d9093cb400a7d829e07da5197f61b41d1e8f6afc4c63659dc83995fd962d6c3397e306373344ac5f469a0a760da8202833f7c3ec5b733d3f8bc11923e623f7a7bb9ccf15a066167c1b1bb90904a037ece1550b77e0729d138b327e4a3c1c71efe022473c23f58a1cff669f3dbf591455fbe4fed3fc811d649c5a1106ff217bc1d2ffec859d0067ce67440fa49fb2aebb3f05604b5d1d8e4f0ca908d7a40dc01e614b7a085bd55b8fc8c2633e8ac5e39c14d85dfc8600541c88c8cdf5a8c680431adb0bdea20841a9cc84b705109bc0bcec4fcad3b9d06e891a838453a257fc373c39ff7275992f1162ada93be5989b1b1d9b67837d2ab5db1e3b8a3e74104f9ff502c3d5bf00a21e713deff629a9ab1e7477430a93db68d7a47d964e1904f4955cda97dcb73e5a89ce964c3a05d5786cd6a6f15232a7d926f87066f4ada279324f4adeb260fa74359c0c2c0c84a1fa73be8cfd039ce8c117821faad14801a198c3e971ce1f44118b7aa413ed4e7ef37341d0ae380885c584686a3f2f43398f6077f79b4d3fe409dd579b6847ad143a99d4440db23f139b5fb6dda862cf7622ef64d34528e67436ad8529cfc98173e620b50ab32eeeb3e61a31785dcaf610f4709a0e5bb4878b7a50194dba750a5031a09d8ec6702413e0d1698fedbc2398c05b8350d0324162c53a28827bfefd95c5f64e63c9803a5cb2cdaa6bf58634af649b1090f893b01820c4aed27db364c8d5924d2ffa7c5de6139ab91f8188803a44beb7af08088e3064e9bdfc91de42c870af4d4c76116c980e81aee77d114d5896d3b87ffa8b817de14fc282b2bf33bfe01b500bc1b525197cdf20024dbd1b0318553f04933983fc08453574e9a302206bad467a7d201b88442263773a3529d4c680c25bda741460ba5ce95a19e86a0640b4641629d1c04a54afe8be890dab47045308a1b979f628ff25d3f6ad5d6c78561fc761f2b332bfe66bdfb75982589db86826b336d73c56193f48d27b937d1dc275e4c49b94d51c161cbbdb5667cbe4665f8d9e2f17d4e1245aaf1c2313dbc4894df5fdf51d0dd4ff8e98a25402acff5c2b9ec772fd6b1198d353363c75ab28ba706729ab545e056e2b90c317585b0bda0c743a6d0d4f65b635cf957112da613ab2f0ca6dd34beb1749903dd9c49daccdcad5fb8fb2b872e52316adaf7dced2c5cbcfb2bc72e133962d2f7dced2d5cb8fb2bc70e733962d2f7dccd2d54bfefc099744d07b62aaf274a46136d5d6b2db9393b9ee8b5c7646dc39c3607f806a01119bc4e0b91865851677b70ecb6bd71f65e1faeae72c58b9fa188b6bd79f65e1f2eac7ac59b9fa188b4bd79f65e1faeec72c58b8fb18ababeee5f3bb938d2342e39815bc5951a911db230d5c012230a4112d4926a24d0e83397b0c42b5ca43f71f373d099574d113cb124468457da594dce3d42a171c04a1c991b64d91f492d2ad4b86eba8981681ddac7932361bb9b07dc968fbec680bec3e5bc2034fdfd7c47dcf3e1b05a7a2fa89a32215dccf2da30cea42697f1e12ba3933ff498b0f618d6b3bb28b4f7e4ac0c6c5b8014b05cc77e51314ae52083ac80f471f8a708a1d1ba38416ba73684319db7b15066f55bd6931b107b00ddcce61ef8c680ed3162bc7e73328669d7e163a746986acdc51f48d635ce852c66909bd32fd109582bc6c07a283854a7a7dfe80c7658f206f241b24171032ed415867da98cafd1123751182a247b9e320db7c2c9a6f03d875d79d2a017baadc04f5d278f1487cac48e01c0db1310bcfdac2a51f41f6f7c287b81c2a03e24a213d631fa8acc71331d4c3476ed22b336622cf107507a4fd4a9f68d89f677dd5315115e4e6a0de8d879a4a179dd42985acb4bc2531b1a751e3d7d6612a0327639e59b32fc59b373fa129e8201b7ed0b2591d09535bf3658a74562649efe81431ca49f67f6162e5794e0be85eec2b1b52a1d1e02d902f74e2e2c8a992e987ddeb2a78fc43432e3c72377dd32c519aa546cde27026a9a984b202d7a9add1d23396362265e973a705a3977387888e3c23a527dab47d6154611bc310eb1322543376df8ad4f74d852488e4233f5ec78e45a63efb99410b189a78cd0702c33712fc48adc6f320dd551dc15301ce4edd24a0b10453090e347ef9cf97445329e5af13432aec18d5a2f5a9d30a489a265a7d1ff53e2ff69a896afffeba90059c56b94f92af82c76fea97fdeb0837ca2068b7833228c5846318f7d394a9c4c7a1e0c326144ec82d08a17c97cdb4c9a15b1a482d47d20c14ac396e5fa0ec3958152829caa93464402842573714eeb1d6e10163cf612b2093ae7388c250403337b61f0c8a9c5faa13b7ec2dfc8d32330255e879a7be65bc20d8f1a162e14ded4ba5cb5b689d482b141d15d13aa4fe3eafa5b7ee5edf39ef1ded459dcb5a3569309706eca8eed8c11d6b9c6f6117a450b54b10d09c8160ebd23c7ac807a069e22d67edda74de7f1f99fbdbf85ebec07913b2d88372b700fcf77220739927942b24fcb3c4d0a1a2b7e66ab0616fae5b86898d9172950fd27b9f4f6cb2a95b32f434996a5ce30268918b9954dccf17964b936c80b97844b449f9b2b21a9bf3508cbd254961237b4b2a4a00183a1a5742edaab323c6170aa4510300c807d0fd80a4af17a20f7bfca81b878854afab82271299b0882c5dce76ea4259d152527a1259af8744fa63f932bbb711d9b4d3b37d0aa94349f78b069c3489db0fa825ffe1aa1424494642d9a75428d572d0962c7a3901fb5b3a850f8b255ea260f7809ea5233ff93bd8e74d8a7d362331662fe29ab26ce5b54165f74942fa1e093c75304a61353e9848a02dcab925885b657c49df5c73d28f336dae9259290c0f9af9848fc4c1fb25d70f95118d8654b5c4fe1885c28eebd174f070e1e851f9002c09c7a473030a42a3863f6b30336bff4f6cda286c0613866b690b09c9d99c69b3e7e1c156cbb28c3700b6cd481757b3b51019acad5e1ac4b5353e92dde733649e9625ead0e9f21abb36961bd9ab04ddd6a909b49bb64b3e03b84ce8050158a580ac48d9c0616cd91541f27eaacfa6c16e5f65e3e9c8c4a203558c03c583f886e20a85d573aeca70b98172d8813e92efd7c4f72cd72bcfe526a97ae17300c77901f7ff439b00b47818a203d6bae25d59661984485bd6c09d80364d92ee00fc6d4016139b3d42bd42148f2f1de25c4ac67ced12583a250394ec959d55fb6f622a6207e45d66deb56795377438ea4b51d95eee143c9c81c0e5305663c2f2bec7e649687a791159f25999cc8506a53dcacd1513b818ced8e7af5a0cb8f051f955a387fbea8481ae920774ce1dfcac25f46c0c336af790ed1169832d3bb6e7c3aaf3735177ed92e707564a4b2b6809f2259d814ae6f8b3ecaf3bdda2fa2beee7f3b0ef76bc8f0f622217f6adc34411d5628e37c1eea8f20214acdca138825ddb484f33e0210ecc700152dd88d88c35edc6c7bb158115f11c4ae339bda9a1af71d12c10807964fc206d323d53b7083101289ce08c26ba80753575d2bbc84b67cc68cc2fb785456b2ba6bd624eb5037725a8e1370cb937c89b39b2be9659745ed5657547a0c58f3fe66bbad2446c5e55925854ff500a02c1231142b0841fc01c0a7e46c41a4c8666b1247ded0426579af6b22b96920906540ec9b292de6c845246c479809cdb5859c33ac08444c11e7306417683a6222bf3305d9073206b2f04e8c780c3357ba8371aedd39d22c715fb1a1a9f991f59e5af33aa1cd290c66559de7aa0911a0954dadb7b67151f6362088aab6fb3840d6ff88013c42e110f18639983c3d64cfa55e83a2aab3b43f7e2e012fcbd2c84a75bc4782723d10429e60261f9c54a6dfd7c2620d2f9e8ffb3e5f697fb6a07c4ab66c6d570b1ee29b1dc5f597d0c9aaea7165fee844e5a2a38f6e62c4cab099ae1b209422d2e5e9913a287f61d36c8f19bb4f789a31b7ab11eb97907647ba333d718924400d6c04adf7b07dfb901f132002f7fe44597aae4cbe2ff2c164fa2b77457089e013c393a1b5836509fc7d211b90a7511206f66c3a36cdae0435f28b0a6bf00358eb2b579ca809bb17ec80f784b288517f92eee11b3f794e56dc29a4cafb910f701f24a2ea3a5a135ddd3154884105a49efee2ee12afbefde9cc3cf84c3c7f6a79d848296cab0a1c6af1c5f524b2d577d36be336e96aa7f6931ed2ec2af71046361d5428e55e90349c1b1ae4adc59c6684b3e31ec98bd4665b7fde216904c7bf6153bbc0a850ecad851fbee086de3862f7810bf172c2ef4de69b144c660bceb0bf7cba374b72b76ac735835b552cd2981eac374f90a642d9227107a47d4b1e4714d412734bda7124113648e77c406e686031b9793f492c287656916edc0024a68c0809d97c5ce291d2e5f3a06da3dc59b8d1fde6cc6f1d81ef6956aef2d138abc728dc1c466f0e0c220c4c9e206fc4080295ee1b107868b7120947803641ec38d6e3aeb550b6f31ecc81e90ad0fd2a845bedd43681b4970dad6cf6f9f0a9f92af5da094046e12401088b4c50da0775f583204369e75b6f3c628e19593b55a71603d0a7fcc2f477e2d291b68c00faaffbb1727578cf7206dd16407b8ce662ff222337b1390eca2bca03706471ea7b63261a190bdc069143dca67a4b8191131d2b4e36cf94cdb3a5eaf881a0816225524e6d27ee57f3a612418147302f6592dc6d435723bace82b01b956233486fb945e5630e66ca3759dc67a9aebb7bb8984237e9d927060c48a65943a77b960c40c419a1392c08944a1855bae402a09f272be43ff215196477c5590583622b200610d0f60ad3ea5aaa3dd880ef4b233fd1c1ab27984a9cbbe5ce304aacd71c21a539cdec6e4a465eee778591131658518a2bf1866b94c36f9b1c77679e98acf576f52d3f13d2f9e9ded4950f885dabfe4747d6556fbd578fcef07619bc3402ce68c2d0214bfd419b096057f29f8e24a0f8c3daf874b2c38f9c13f722ffb15425f380a8761b649ab99d35b5b7c903ece8d34c7d6a403bbe314d525ad48897f16d0648cf69575922f15505b0b2d83c60237a89d77a2df6792e58b9325f6adaed38eccf3049ae87eac38166c9e370a3b4b5352f2e5a1b7abc0f84355cc52bcd763a3c23d19c266e553e07bf7b4a510d2cc18e737f3c0f6cab50d7dc714318e68bd04fed6db643c81b8b443cf817cef280929ffdc09b371e59db45c87097be90d18ab972752f59bf2278d5e88f66499e0b2946df96542a575090fee82491ac4ecf7bc0302eee7d681eb4337c7958bb477608233260face943dbd05fbe8b9e297bc7a7e4641089b99333c1518d8f0085be0f77ab2ddf3a2dfdbdc501749e42d073f4349554864ec8974a9e2e46ed049299be1c1d727bff27cc5e69abad04a9968d982f1e9a9e1c8d02a1e3f8792a89ce47cd6fbc4a836ef845e72a6184e23004247c15de57c68051471b6ab3482b784198e3429133c4e34ade585ecb7b310c38c34465565d0cb09cfd62ded6c1e044cd2e0d8c8645959536600c1a7e141e7a8df0f7514c7d34aa9ef07b08bdf9a74cda59324163acf7040d8a93cb8cc8a2e4b4f6e1877b03e226dba58b06a5eb9c983774b0698435e79bbd1c081d88c2cf26f7988e668246b77066cac19ab20095b31df4938542113be8f05f3bc84c90fcc752c0ac88214e463a928c184fece897fc6ae02acbf3f1c4ce812c41f377f3a7601a43fdfe5845c12091752b61e6f36e18e2270a17a10b11841be0838b575223c06e8a0e1a4c4456ce801220a5454bf04b554d506145f97280560f897e9866b281d422f0f7656a949139df53b0ce70b97aaa73be88e62a69438da2c1957162140c0a308962dd6646273eb20af9ea369b1791d4264605a12446006d3c62a93ca1aba6b265d3da60ab1f69468029cea48bb726960352a08d230939b7be1839d6da0a258969e1892ae0d92c3f1e499c268164e12047efe0b920bc7ddc87b74ae0421a84bc0c3ba3852fdc54908998a79374bcac77c35b5fecdd6ce676019a23145431a025301e3d4405174c022444f0175dbc5926d41e81fd09680f2145b8ecf5f70c9b585ae45bb4ac06db206e62d361271b51f386b40213f9238911547d4538a75d0b2b6d41bdcd0df82fbffbb009f5354f96484ca40131e54ccd766a4295f52c7264130cb9d73fd1ed9740bbb1e6f1cdfbcaf0ceaa1acca1a6964305717b82ca20a5af98a3173b3b094e73869af2a7db0c55fcf22d151fa6c18f14abd8ff96fd57a10ae90b36dab430921674de50b1c8c3ef532c1d862c2fcc7603ea62e9fb853e9ac6f5a65b3444b0ee68bdffd206ecb18b5790be1d0fdc52e36630b5adbd6885dc8e9e838c4763353a1d63bde93f6e980e1406815507093b7e439bb44cd4dc2401968519dc67edf81c3d44db450852a8db12458525d027eeb0bb4158de369d5566a4c7be52ce5ff622dfe29b425a7400725b5ebf22d03beee306e53b441d0d471086e24d3d2d517d026abaa40d9a7eb996a13c688d792390dac60948cd5054e84895d73aa8421c99fd169a629803d128c0f602b94c1e1269a82246d8dac6761757c64dc0f9c7a55bf0791bd09758547ec3f7dbc62fd04841f59be9a6c819c9e2e78a2f0487a4ba88f0ed1622bd7d8f09453bb3c31aa9e8766d7d8dca6f59d94d75e509ed5251132cc2d8816bd9656b66eb3d07943a49502c0d7d6d30a132f6adca872df96892be4283b2e4c436a6c1207b6175d079953e5fb4e0a5498114257d38e2ad548bc1c3c04c9a12cfa6bf38c9c2a5cfa0e208204bf82b1303c56fe3b4dadd1b8ac555171111f4d1645dd8d05d58f55ecf60af214f89ee16a5d3f3e6f53a884ba2a0b499b6d4e627ba8d61061baf350cc324878124218a2d44d71df082283212b6bac0e5d93561e8c7791de6ba131b1d67feeaa2a58099e070ef2264ea75be449f70a07bf98d181ddd51069d0c3790c1dda3ebaa2b0139efd14603029a190f1a49e85bad0720335587123c7237cf8544be4a463e8a8b56bc98e34280d5b90f06fb9f6c864260100bde7da0b0547738387ce379cd66418099f0ef031327cd01695b408819c64c71d75cb123eefe8e9fc10989b6813be4305fc5318e0fe229e4d368b189e7645aee8849a49cbb8c69596763584893d36f42c4b3079cb9e098b71ad6d411122c6b081509d037120085649679ccdf12b8c181fff4472fa38dd4a54669b9d1391d935162d1a56b80b0b465c09d3785c5666a8c24492663192fa80324f93070d09c9e87779ba7ec8bc64c82c72d49c8f06b9e9f44d58cbae93a44472003ed40ac427e5d0f6e54aee8a8e84b67ec92d21c10aea0f3db71e41be29868d732127038a8e4ae758ca2121026c5a179e70690a23b70809abc9c290cfb7b5bc0ece20896e3764d478b03443ad71e05baefde176bd201b0acf173ff8f30babb5fd05b096558d18242b0b92935ee8c680564a971e8212b48d238237f04231d1a31cafd41bae173f835c0395cc24001b0e95453524733cc625506fbb3f9e67d09d04a6f9f7efe9cd3e7447e72c99356033ce8e7e2ce2a9bef5aa45fedb37920ed5b00169d1325c0fdee01c0ce61a4bfbc5ff3a1bc062d531c8afef5d00814c5d671525e71a1df1a63aaa81891b31e4376a13d7cfe677b4cee478b1da1a90d10b5c07602c83074f33c0755e365711099f07a13a672da4fb4b003bca2375d8c080fd5644df931a8bfa046075d5ac62cbaa49104e26d364f55c33ccdc51e045e5aa03bba1c5c7efef1bb3c952ff1b82e8b061b1cbc8dc4c5538428ce4eee51e57b6a39428aec4b4a6da33aa13057cfdfdeae376e1911da02c6aebb7e6ab6be955cbd2c5cb63bdf2b2dfeafed7b47f489a71422ca6be0cd8fde519c9e3cf88f1c63c9530a08221c015e2a4b23f2330d22f4e0b41db5627cd914965c382113535c3efcaaca40bf7a55012b8a45530d4e1322e36d2c53c58886c99caf51bac7eb6b0aa95a4552df5cb5f6dc7d7f66c0b96eeec94d1e914437410c17f7f5dd3ab7b99b09f4db4a9a40c5bb106ea34970e7515bd26cd188420f893869f103250048b1a017c8759ea7b1fc56f4c65242a206388567c992a6a8b36011630c685a997fa364799f9f10662c8c58a6e636608c177d2a2e230e9d8da89d370089280f22adb54d7f6aad3b956e0f91cf3d3ded5585d37a39500f072dca80c13f51f83ac981345c657afe314d86e8ec4141be343422a8fbf444248ce107037b336854ca28dca0e6f67a0d900a1581c222fe6a3622d6f7a1d3d9754994addb4e77a66ce88a8f78d09089f8b6abd17aba42e1704eb8e9032987ecada954252146beeb01f3814fcf64bfd808026d82b6c23a47db5d95aac03c460c638e220a8b0d2d3b5e96daf350a45278148757a7aa7f4b748392f0b0772434c2e3af4c73009709c56fbab5e7dfac7c0e0473c4ccb17ad625e1202daf8a0473ed7c882d157e479fefa8e398ddf66162e9d83b7dcd0b027a6bbdfb33b98fa16d819445eced39ff8e41d8c8af64a30be23f9f7b5cb75dce27d84a97ffdd627a0a411c3aea9f7d7e1f30b52eafa25d8912c4103e55a85aae041edd3fb3324ca9b1fc3ab7ba809762e15f87d15d128a0a2b34a361e04761569f410c29e38da2cb5db9c81d55e3e5177a93c1deb4a09212ad1328ed80d7745ac73f82ba6adafd63e883d5a5d2a42e8fa8c60f9113a53ae151f9b02cfa5b19eafe396fce1e5431c76713e4ad1d3147f74390ab3695f302b337616ae7b4f6e87fa61b6af5ff387905e3443f1de0b6ffaa86e02ee401c7d34e7c61a81b397980e7871ffaba755acba054582fe14088a3ff2499fea4abcbf0fce5339848f5451b0b01440dcbc3c7701def5da8de500b04acc3ab172fea7eafad7a4f1a2a4f58311a4384af7cc4c0baceb3d9fe59f29be09fcd9356a98df3ecf5ce3d3748f05d8d904cf1da52734a5b70e667ae275db3674845e6eb34969e94ea41cb59a5bc897c008c9cec088e31e3056f077c72c50241aacede9ff77ed61dffff01e3b5b1bbb45f814c0c9007c081a51c5e9ac30560c8d01498e758fd22a63ed9630f79b36f950802c6b8db99b1821f22106ced24c0bb66e5483779d6e090596ef353c4e3e9ba9d19db1406dfdccdcb5988aef35ab6f7f066127000e0ebfcbcd6e03cbd356a5cca39cd5c72e922e6abb05658f3924343b09f060b73cc34288480d383784eabd452bbf675ffe1154e4fe1c444652503580876fca3da8698d7f873f91ec070e396f421139acee847958980c6623224434170f3d0cae04133e0d13e60b3f71d88384c74f1a9b4205f7b39dca8c779c1cb231d7ecc128c07bb10df163bc1a238ae6dfab5cefbbb407d723eb9ea4000087ff957c480dd2c16cebc07ee486f5838b086b5fee2fae123e65162bbca699e16c95d9602d32613e11026cfdb2de5d5c7d8df6815f70c4f0bdb84d46dfca04396c592bbb5c89e7b90df04aa331c73c6a4146588a1d5f43ea83aef28ea700e223d64e1918167b8f067ba75ac00cf0b45ec50d043b381d620d629435bd0339bc549d62a793926d41c5a87d170cb59f1841dc89f3b18d42200b3ce9713552d5a5dcef4b221b9c183d0a39d418a2e45d0c36884bfa41f1345f91636076b2cf5abe4464857df2d46cf207f5539add3e1c6b39c9704db7a9613d2afa691ce1f34309f598357f06aed186ea8270230c29497065fb8c2b8632f279c0713c652a7735ef24b1f743500d9b45375a2ac1e09778bc5e814ee665f5ef463cb5442515556ac18f8f4449ce57f8c3dc08d137bc06ea342c3f7eb133e45e76f55d29776a1ebbc83509423c2604ab6f613448038dbfd9a8f44d3891c22d34baa546c31e9cbe10c44d8c4655c3f08a2745d6f094494ca282a5e460f9ad84423d610d155e76ab5b2490ed344c00bdfa15003c55938c3223104b9dcdcfb5494560bba9c788b06859f5ad548e491789c303f876aab89e57eed1402fb6ee2967614f09ad8d19b7c2ebf6b747fe039a9ca17e2555e7d0f63c39241a6a754004a7de7658bd7378ae7db1ae8af34c1f2bc53ac67422792229784e1102973e8126e410eca01cd323bfdf064f3102147d438011ce24c670509c9440e1829a8aca0ac92c857f65df38a33994ac6d6784400b5265e6fa81298c24528399669200b22b58a4c51da441662ddce17f6b45a696c5b731ce5de8feb5fd8a1c7d5a375e99a39ac4369f09df0f701e066573422ee1364c862c559127564405a8e41e51d84aa63e6734a27d5ae06935fae7beb6c52ffb46979a38bc756e1aa8b7d72c7c050a1183e96aacfd6af691871c7ad32d7990984a4332a85fbf3e86096a1bf327d664665231e63a841c0d0f2a149629e819e83d7c34e15533ca22260d9e75cca57f51fe95017742e162f547830f6ea927f77ef08e6c01678c731d1b81513df51c49a7d0e14547183fb0245f93a70a539bdca80ff841548dad8b57fffae7a721c03031173c287b14f7bbda48a2acf09c17357d0331efa7e831677942f829a7d988613e439f24ad9c2caa80f9645cc77bbf026092caff40004cbc262f670669c4d617d7781a3fcec46d29d0bccd2c264c2759421a898a109e637c881c6ab645c6a48586df6942c478ece460873b6b39a09a07665fab372c7717850b149b7ac437090095fceaa218e05224b62a117f764925dbf51c30e9ce8adbc7c12146da909f44cfaca57036a8635d559a875c81435859d104374e1a6dfe1d0391ed21cccbc424a14cd40184f342e68d23ce91d3cef7841977e61078e2ebd1da71db6b33cf12d52295217386e562c7e03feaaf751745ea2b5899990a61dbb314e1aedc394ee4303babbd75eba4f4a0d6383c357b315406802f1ba330c0b2aa4c751744ae0b570a343f9560161656a296118f3f3361d443149044b4dadd286f0ca9afbf450e2182ecf9fcd5543359f4384a38c3a82d901f763fbe465d996bd38817135f188c738b4fb909109b6fd2871e88975b1c6ffd334581c88af316df50db37861c5841c12e69866f5d17db4e78387955d46596d5da5a2abefc6b59d260210599fcac9adaeebec979bed829d1862dc72608ccd8cd8d842c1131511305d826d0f560c238800242a9de37f9a3f7c687f9287e21131ce0e1069e02dcc2a6c53d13e6c56302946498287e3cc143cc3fc2ae10156dd0c3fab0499d959fa1e8700c765098c54cb9c84fe0038d79c07776ad7583080265f6e5f7e4c28e9fd1674cf80281d568a0bb2449f685befe805f3569a5c210d620b19ec1eba1df9fad594b07da3f1041aa037c669c056788d700d16088e77e216f39e539d4284aa6da382c277034662c4341c0e6da206e9e15efe26b634cea4e7d71185641e1a488189cb4f4d96bb24944539039c70e91668cffa3c178171d3b64731eed63b266c49a8846370bc1684359488e6cd3a6ecd14150a83e060530223b1c50f6440a288cf025619abad32c6110d05b2b8040af037f209c6274aba81b152141317eb3fb0766d6bb2d15ec75a48391d542f07826d38288d2a37007e7736fb243fee4f0f506630f8de668081fd53ec2ffb59562442215a808380fc1265028754f2c27a0ceeacceffa6f0fc47de4fff084a14c9f561094995c80f4987facb124d2fa3d03fe6b05b95cac244ad1eadbe160dd6d1cc91ea0dbb2806fffa3d10da2009f2ee946b76d94813749d3e346a1607861176b678aaf64a9855532d5753b86bd97c7cecaf10329381adba84c4f2e86c1f43e1558d0896d31dccfb6e7300e9d9de1c72edbcf24da4d7fafe4d336e011f195fa3bf28e62ad18879570fc1b4bb5b767a490c305bd3046a22a76330ca264814d1a07c45635bc839159e41f07b3083c94b876e3689717a2ab8022af0d17a4a04221704188f9b2b4c5112dbc2e94db102d0dfe661c87b2b1ce9bfb43135849ce4d06be6f996dab1a06bfbf846e3335c01da2d08c5875ef81155b2030192545dc87fd7084df7c0bb19bcdfa5007bc706b3c9213d61c8c2b03be92a406556225f8536a13c8f7bbdb18ba14b49e9dee8008d3c448ecb826916572079a1a74e7956c3f4dffc3d3ec836be860e04536f0e118d435f00f4a0d07b87b35c5a80254ca3807de8252c13226708aefd5fca425697a6c1bc2c87c60d2224aed8f5e175c73058f15f89c6d9cd9fe5f384fbc091e806a5c73d01f9279aa023ce5433852228beac7059443bfeb39b8b01b456e44b2a063b98fddc24d2d37a46447e66607af1da9683709d220e49f4209a188dfda9c80e2c6a7a987293703b673a14c7f8b525912ca9500f2c1be6aa9e73376ea62b226d40d2aab789c90cc082b02169b2f74f0d044d6895fd45708789d06262ca778382a1e2adac7314301f9060cf41c1acc22c68c2132c226f952f7249e623a4127b14966247468093c1f0a7438106976251380d8617a37758187b81add23755bf5adff003abea3e1258d969760d7a0033aa02c0d45a909c22ac31cf863af45330c3e0ddf04123823123140fa7c95e581a3bc07649561b4fde04b9ccba67731810f913d78e86a8310f8a6181cbc258c90f1a53562130ba0752f575e99984cdf0c0aa819a8e6e5e2178317d0eb8448d2d41c139a132980cbccc7134c0f906c7d57bf60e0db3a0840ffba268204405aa015697cc91b257916bf86e91504573451d05662851331c0eb4461d85ad27e9f5302ad6414c96c1a79f772e628ae9a67e2322d1879f5fcfebea2f5438091eacf757068b593ec4b613f410001fe040e4cb597b7979ec17316c1b2aa04db29d47ac1692d8a6a8bb7b11cc9883e1322706bf773705ed87bfa498943eb4ad8daac5dbaf7ed89692de682f9d1f95721142699f457f3cd3e5082dcb1062bf8f7b174fc3d5434ef4d4b5e18566ca53abae9b5b438d92b259334b1dddadd022345eae820d0e3fa8cc9a5b8d325ec3b2251d0d7ed6d6ad6d14ba4d6a11e72f5146c24f34a030f0e08918719046adfcfdac714cea1cb35d59f35f06050f292769427c999e042b79d8cdfb8285d6f43f7dfb01e6edb46492428dc3d29f33f7bbd337e6e8c429fe2da06d3c10d366e1d88f37dcf4229a7f7792ea52f04bfae049066325826005e1315d4c68072a994de74e166093cf2b897d0cabbfb3f20acbcd311e1e900943f4cc22c7682235e2d5355cbd74eace32068421f920df0028ccc594f5e33425eb4eb75704a8e56d004e6ecb390605d53ed3b0205bcf1d2c60cb196605d5be67acc8386fe73a3b292ef2aff1e173cad3b783db87c1f82f0d4d4f434d778177a49cd9338e0bb073de5141769e735e80cd738c14a0e9dcb182b6ee338664b1da5a24880c96950b52ce5dc75853a4371274b4980ee16934c7406ff819dc40e9589ec25e19e0f62fcc259ec3d04742a1c087d431b9f3585542b95ddd532afa76dc177ed7ba264068b131981b2af85d173b3fe9724124ee70d367883a39aa7d976a9b71dffe6bd57755f2b1b3b8d74c652beae6cd3f19ac343f38b4e81a1c4071d06195962ec44596a9e2e2086cc6f339d98958b43bf51a44e9788b26518b1c5d554df8f02c6fd151eb48c28db8b443865de2b646aa0fe4830e2018864f318f4987ca1c33edf7893e8712e83b0fb479643c801ed5f1cb8646893c4a73b31334d22df037a76921d680f0a964dba3f20b07544b9f3a2d288179dd880df9255515fd79137899fb3de092ac68a630b867d6c797712170f9334c60ba4d85478f404c1b0a1a5f61b7d2ddaa6b08648027541c108edd2cbaa6cbe8af68ebac6f2a01c7a7dd87ea31b4a9ffb3eb048ce89577235ae3f198b35f1bd4aa0a487588a632bc8973d99fd27e038ffdf9e8460ff60e14deb8f85f580e4508c8bfdcab1059d3d609df9f801ffc54f349a8cf7fb750c73f26b2df4a2a2cd9fffda57865b2ddb2c0ef781c8768ad199777ea8f54c60ec87ceefa3129ccca95a6a1dfc43ce340b7aa740d845276c5bc66ffaef3069ece5069dbff40abf350b944ae2e33141c475af9816460227ba34fab60564630ba4afdc82c7aede0b40cf18bf7f0d673c46c532fa2aabb068bb08e67942eabe5c698815c9c9ed7d298294015fb757a58a53b04ac207c8b20b20b0ea86c8c208fd0071f93e8c97229247d78cbef0968b8e78743ff1c86b9cb33107d646ffd3afad60ae8a0e13544622100c4d847972af18eccf418016dd7c18b082e7714756b51aecc9519683d187506cbbf4883655efa7e8e1fa67f19f4173c3702c25227c5e4c4396905dd6bc45065e94baa3fff9d158362576332b9be3da30eaf3c385e4808a6be0144d49aa4dd6ccda0702eeaee03e082e6917a095d240ce125f58c0bd4bdf09635048d8fbba44577d39e509d8650c83e53a11ea22cac96dd0ddfca3a3d164300315822abdfd3a3f1e83514002094b527c862616c24cc86ff64e091a46f7ae396aee50d2f8b9f1a57f377fd90746576921ad43f9720fc1f60f222bef8f0f1423d71125337ea07eed1793fcf0c56cea3766d5770b05e56195a48308acb50970e085349e227bffdff46716d76ced45d11b40cf29aa737187e3dd187b431039c4e38b0e0bc86fe4ba16da068d5416bed0b6c9a3c18a4f239008329409825020e334e1a463f19a6880112d0b45b413606feff76409f09ac92e6465455a234f134907269158a3c09d9b89615b0bbe0e68bd10e56e69f305684f8102999ba8a35c3886b443a044331174cc443e8c01df5a0efc7b8ef01cf813bbed5e15bc880ad17761ce5f78479830f906e9d85b874acf9e497dc2a6c817f131d8982044428b84b1278848fc51f3512c7d6603b2f13479d5b0534652e74cab8ff3a364186c0bb6e720d1d86546f05d5dd507d93f66df52856298bb525cfcceb070b1fafc397a427291dc57a7dcd303dc22a28e2561a97d60fa8e32c07cccfac93625ac316d8a1dbc271312bb5f881c827f28b3da3d0f5370c1493a46458a90eed295ccca1b0853feb532f6d4fb81552e60f8fb24de95201d4d5a232a038b1d48e37343774e2f75fa1fbc8cf62acc9b74a968f771fb520278165e9d6fdcf9ce1a431a31da16f3cd230430342b92aea77249936499be2363f80f35ce717fc81d0ee3570f0067f86556b70306dbcad82d1a510b0c4db683b11a4bbf143dd8b8b52230a52b58b9e8aa25d2aa83bab58413a0164b75b6997f955b68214f863d214eee9e1bacc122dd7ace81b29c9e0e22a3aff587c96a70c156d4d05c60f1341f289b60eab15c7d1204907b49b3355c5b152a8676b17bb38ee861689b7eae2f8fd73169ff43d9708610461b6da7c4cfb8cb85f974160db45aa601ca36fe7d3cc296d512b8cbc645875c136a7f67fd72a908c9c8bac80fb0a67f930cdf5764fe63660aa5d90e9ac2d065eb0dddb71df98c3822a0e0576f266ad33d12e067db70fd476b30704d7b7eabc0d63a66b4ca9b1f484ffd7043739ac4b49841754afcdba26bf23c2f3bd4c5cf3dee01eff7b828aca2919d01126b3af67c45e3c0f544e1d2a186a30dc77405eae58aa086966c23fd3665653d744b54d7e6cdfd1dd0e90e924264dbaf0e21c8d1ad2780db39e22d12e250e79cd638367d8fe52a02a7e22e25386e8dc25f7534ca8a1748f8194fc4f13ea4971fae26279cbb6761a64bc310c0e701c53f5e5a3c33e098cbb821e428d6a42019b24b1124412ed322e0cf23cb40c890aa15417fdeffaad423c92ba86282fc6b8f41085d78a5dc48c14a5e15af92d9d9c9c7a39a4580117c09f0c3abb28391c0985acb773282cc9eae6d8fecb860aceac44d049dc0e21124e6bc4131892730e0d154b7f2098e9e5d0e08f835215acafd6636a1db91e059b93c09d2fd8c9a1d7f6c290668f814b51859811fd5a5e4bded124cea5fd56b88e7b0a9c4dfae8759401ee5a488fd9e41a250598e8fd8b7593dc6a825779a4b8dd19040548a641b7fe16f1a0d757b23a079b4c1a2ea2d904d7a013b0cdfbf5d05064482d77e42ef7c4e4eae28bb0904c758359a29d008196913e282cb652af74f1ab044c5091e49b505130dc46df4784c85d4f28ccaf12e989d15f6707cd88a14bf90499a01ecb74dc6bc9b65ded2485b719a9580ccba32c253087e992ef7e4039f8a5bb35c3c790ad4101e303861014b907da3c4ce9b1b6c4d3d92474d2b88b137eb3dc5e6d7ebd5eca867f32e023170cf5fc89f911ed69d2a3d23e47e9ddb27dd3d89c938ae62153f16345f8fc8c52f8c1c3d235b70f104fead271901680ed85f11e09e7a787491671ab3634db8d3caf991c1392499622d119b73b7f30482526a520c13a19884ffcd5af7b2bbec2da04f5ee8bd87fd05cb87dba18337c62bbf140b33b1fdb51c61b46f4ffbf6805aa3c1c9fb86c20339c220ab9f19a39f5e3f404a3fc43211a148d1f5411b962b6e626fcaf81056ceeb34a7c2f5cf1d3124bd1947d1f1a67e43159cc274f4264de26780e689852e7856e42c1e7cb33d018c9a1efafa0c1f1f51c7820a470ff6005f2549b0cf38825943ac762ef32ebea0d3e7026ea5330ce9f65be116bbaff49f3696376477c654443aef1a00544e419672e24a23644c865d5822108a11a9623d00844d4608d64bfc648bf937ef426d7084201696566edd360708194e0359d7385eadf3c8534c030e60379bc73ce099f89a852b83ae48c70f988562464c85f64cddc4304cf55dcf1b4e2818f55add49046f277136d84ce1a1feb9785258677c927d7df46ad915250856d7cf172de4480b0a56b956eb546541676197582eddd9bcdbb883825140ea2441976f33e3178210196cd6cc209d2f206c868cf26430db47d547a57243fb75f8ac9cd60ce0a230d33aa832d018236a5955c73c39615b68d41e3a931823bdc8e448dd1840080cdbf7c3a460bb0acf6d691cee6313b3ea016fca8279d1050aeddbe4bf8ee0b065e697d4349bb37ccaef111a69f891eaffbb45173483d4d2c493c6a8a28336643481c295ee366f2879b9d069457118e67406b2c0be35cc186f3942c428974f1f72ef943b46b0a96c4765bb1374b1ae0148c064c05e7347496dca23885ac9ebb1d441a7bb2c908497998bd79959d82166a51b3785be3724834587dce65284ea903a43808a1f1ddaaf4d261d0a910afd76a5fa75a19a520fb72e775167d92e2c2ddda871832e391ed0ea93f243ffd002631ce1acb8fe2a9fae0c8adcb2d8120ec8abcd919817f3b32890be349e82313033a934ac1122e9d87682825ca2a7eb4b1392a423a23544749d3ea5f48b97b140912545737f12da5bf92195f235d7f4d16bcd613d183e5e06d9da0b378c3be186ef3b4ec46cf9c10dc36c60125b3dba054b8bab65c48ec2775ede86c9d91ae08047d896471500e5b6ea3a35a10671b19c157b9838f0fbc8046aa77b34029525d3aa65cd6207afe54feffbd1a8d6d5be0e34cdec8429d7bc833a0955856321dbfac8a0d79379d05d528c82561ba541360361c38d7f35ecac6c7b1e20c8a4e6c43d24f08fe6cf0c21853ac0b82102651c56bd07041dd211305e40b188259216215c2e92c220832f892cbc5dc5f604d70dcc5d6780b87af5af35bb5fc0be36940a287b07dc841b8da05518b13deacfe18115a18930236a8ce5418b6183197047b71af9d4f03500d2761fb4471570a527e1b840366b00e0244de8896164383f6fdb2d1d07c6baf04c1d1c7d128dae850472749a1c4d0423845b479cb5d4a6c4339bbd12e0603dbacc2fa877e8bf81a427a5bb413b047ef841ee2d845b645d1db76ca415407de884a88077377baddb5856374a73c20d599fdd6558350246600770618aa29618e2b9faff17f1b71b423023b2218e96b8bbac58458b61a32fea4fc770a737711ded5581ce737ea449699e14b97ee86fee48cf826681c61b0fdccff0eca9f5ab1854c2ac4ae8d105f410ae44fdc4376417052854ea368a22e0f3e64b0aeaed38413073043637eceb135618317100d5b7e8f301c2b7f20932d5984a8098204431acf238c868d324243854a539294d94c0aa4224f6d1be4589d35a137087fabd0c70ed4d5a7e6588ffb889fb89bc9f8579283da74a84fd1245f9b094564c690be84574a8690b7eb08669327dfe7455a8cc2df256a707f374dd7e7939d4bd5edb1bd744101049e15500586f816ff70423ec637aacb49bfcf39e845eb77cf89cb92d4a740eaf6d5de3f673468d899ef6c9a9ca448ec00e920db93df2f064800ce405915c3f5013e4fc43784c8e7592310ddd2bba3d33c5642f93271ed937962e287d73b5a4c833a189f6619bce1602002734ec9f1774fe423f4591d6081c11801f9d3fa5a229e1e3c7d5178733ca79c63aa4d1d0ccd9de7d39cf00a034fcaa4f0181c0a37536a0e08130d2bcfe4296230cac96a21888ad7debe700875aadb6382fa398e29512f03ab47e7bb7da7c594a9f92d51afdb30a6f8a63375b51897080555ff2b35793a9c395434e1dd59b789ce8a996856dd44b7e626b8553bd15af109d6aa4f30d6cd44b3ea26f85971110f02b271d730f7b49438df4e5fc9d06dd0f747c2ec367d66ce13f4309998d2ace02ed3650cb7947855a2d2b13d3c3c2c0d4c076424959d3ee9a116518561c7d06422470ac2a522a036b656238fee19a2ab99da1e1e19584e66bfff6524e384437ef9d1d52074bff377b2e35d4d2ec6a7d237f917199c5e0cc4957b416888eccf6051df1ae110229de11412dc3bca6edfd6bd85f0efc5253fd5d6aabcbe08665b274fc79b37dc0ce5230461ea790562aafe6c853e97669a687ef97f1e518d71af81dac464f1188feb3d9c8f80e579e25af409794f1742bbb9912e3d382e62d328a77d4ff92bf33306272be12cf839752dd96604f7d58f1903c336c935e4a1fc156d84ec012368a7e8c226dd5240bb68555674639446a16a5e3e1431bb37b7395bf119b13f292f353ae85984e3525a959777524a1643c3e502f9b36f81d54a62da6c845a1a3ed561d0d095bea9fab8bf9e7afb3e26a1807922479cef79c63a7cf2b142238dfe9848d2f2410467240ab8c1686784a62ac40536831f86542f365d8c15153c1283fb4c47d9386929e07839cbfd1ca0002714608bd789ccff5af86c2ae7b2db8e794d0d5584087fb86d807d33f8eba0df3648dc2f31fe8f80256c51708cb2c953eee21bb708d6919fc8d28cb2d901d0ca90c03a545e38f8ecf0831654c1f5b4eba04205f6c012bdd9c03d68986c3477391d4f828c0435586cdbdcefe2ab71c46892bd7320df8eb18655701b9b3d8bfd3cfc48061eb1bf03b37dd619e2a8122cff28a26448ba180682a9ebd65a8044e196ce130dbee2716104d4ba30993e823148681f105255a26f9034c91e925ea2c3799094e132aeb0c87e1e31507311e5b8624642bb423b76c90ea300e271c6d62760d68026571977e4e47c7a29af68e41d03ea6fe67a55205e554d072f5f041ebb5c16cf80a54a07cf7056a0791bd3cc5373eef3fcd7331d632f22b5df29554c6b8cb75e17611be3d8efa8c9fd8940d1ed80a71b3b75475133a9942b87a7e6a9090935217bef2da5943225191c087e075907a377f11e2e7c11c0852f01b8f0050017bea4d457855558eda93c9567d5393b3fa72de4f8dcd7587dd5d89daeee81131065839e576f4b96bc32842adf52c15965ab2a2505aba4e870893a2c144dc88770b5ea565f83e3ebc7583dcf3765d9700c8cbab45bdd7e81918e7ac95f6dd98e77fa61d9b841a3069ec1baabf76ef737eecadbb8ff352e8ca771efcfb83c3cbe319e75e1cbe9e70474fa390165581b12f5a89b07183162702de201660a5f6413db39661917c7ddb2c6edd0df4a69a9fcb7030f2218613116164c53735fa506490dcba7d80075500b0165b85ae5f82e07ae51f94b4353c3f2298f4446e5ef90dfb886583ee565eeabb07cca1b715f25c7db742fb3faeefb3b4c83a4314d4d8e57d52091c9f1d526476795e339301e06ae810103d7a83ec7779886a6a6fbfa4864549fe357f085c77bfce53cb9eb97e9bebe4c8e573d1c758d8be8bebe11395ef55858791efebf97f1fd8efa50af158c72c5c7990c0c230bc6bdcf02e3391e6ebf64190fdde5e20dacabeaa8a93bbdf1137dbcff503a35fe43edd8f80fc533e33f540f8dff502f140cbf77ebdfb8aab77153bec655f9ee1faffc0c1e9ec695f170e4e29d2bb6503f3387c37463d184b69d762e002725db8e00a416d08bbf13a1b0b37bdbe981dd9e0a2738d196481040a18c84f622516f3bb1456ad29363566611c8167d031d825e7c8e234025bd9af43a29392d79b50fa7249c96a0841cdf5f3e9c5ead090df90098b0f4730c70001289840097fc920005c0fc004410422c80c7104430a001314538e00132103022023d2430010a1c51010b5cc0070632a0810d70a0031ef8f181cf63e956d543426a5bfc82dd5e8220042f0d065f5be69208e2d588fd34a1785242821294a0aa7c260b13904e80021a21d5e674f399164bc8f10696a665c0042a5cb5be90ac0708f65231129144e53cf14d5640a726e42db59041a7977b5ac096d312a0177fdb29796f3ba757a5010b5a703ac98972b162033297e469fc653b3c3d75e64e0b4eae26f597582e8caf5da83f39de3eecde277d1817a563baa81c5745f2c928120aa8710e6a175ce01af243a58135b5e6a9289a4994c0a2b0d9cbcd2706a7bad7cd87498e317fce5c2fb85ae65c23426ac272f3fba2e423957e3479fabb44dcf5cbdc3218baa68c52425aa2fec01dce4477dd350f72d4428be54691e42569db644f1a4a94d250449506b6e6af9e44950616b5592125aa34b0269468dbe1e13828da7e3ea7a23282317dc72d4446d457e19457a15c5c0c6a923b6b4cbc0562717a1257a2a0274e804cefe24142c8a794b845163dca65338a5282e229a15c167f19de542fd216ef8fc47c52102651c1f913c46024b7063b7d0bf482188a147192065485edef14447a42122205b9f7a46fe71a5485fa554e2318974e1272af0d70079c53cb7e3e49c3a86cbb950796241484857b5e24b501aec428ba3097ee87ea71e22d730b6f210db50f7e43c2a2d48d72edd8919348292929aa26293eaad18e919dd4cc992ece858ae894223afdc01da7532745133370d4ab3e61bffa5383ba5fbd11f557dd4a557760555ef5df1cc5e0a8581d57d55969309a409d40ca778e6356aff2f0a56f29a3727446446444dc6b40e672af0655a15ac44e1d9dd3146ce7509a3f920fc5714f0776e3d9d97260b5ffb61d920e28e5260e604b3675b0aa4d58983f944be5498f8a82933b9d237e03a145f41faa0839b694fe432d01e50403d4ff505614c0655fea7f2829d400073948a4cfc1d2a96088eacf0e6cfc79f69121ba24adcec06a5f75ac7fc581fd502e94126f813167e22dfd2a548f8e0ce00b724cad20c74709f9c4d68686fc138182d200d9807a4346cd618e84e8775c6f60b7114cb581d59e1b9daad042bda0a108ca81179af5a16890e38b2a115b6b60b5278d789cde9f1271fa2e898e47f7a8d2c07127732491d24808d1f7db9110a76ffcd57c7a534e509e0f212a85e2e2058993da49342aad72a083ad48375763607b7391cbd111213a5e90383e523794eb67e077abb9473130b25ac6f6edfab3dc249f1c1914d92a0b9c8831b0fe037deeebab3e0b4dca42723de880e9c04991fee8441d6263d6b1dbb6ede0077a033b9fbe0dac8c4ed86fd621b63d7f2868d819a97778d082cc291451c0c0ceef99796044ba78145b1d62bd32612927fbb756dd564fb92ee2c40eec97bdc0d625ec9c459220e981133c98ae76d2b6b9e08ecd8a1a3cc90ee4caa14356d460498ef185e42384fca572758185a92d10d51b4bf337eb8d3fb759d8121814e4209a2eb863c256add3b559d557fff9137713c6dc6312c3d9ac0a933e9b3c7177ca908a262461891bb861d24983f8530e2648e7095960bbe234b14074f6e973faa415a7ded8cedf74598183a1ec390c56e000a88390bfd4a9735d81853866df460d98b9aac04ecce1efc50b92cf8bfc6d3e312b8872b879a9f5c6ceffa62b956b0aecbc5a86f46bd684bcc571275f4a5ed1a74ff7e9fe9dddb76ddb46a2e9ea2fd51beb2fb273b0540e760221731cac9321cf872ff0e543b972cca825b298812a533858bf59ee117d83fde616f2fc893bd993c4bd9a650fe706db3373d0faf436d8fe2038b212f33bf788c7cc13f7d38bd2812b4d40567c521624a00c85e79268ab2f9dd8c190eddfc1136c70a2dae289d79f277676a05883a576078d12859c14a54f3c7142e57c28222292859c0b4a0514cc9029ca15b38c137dbd3013dfefb3fbc8b355adbaf576f4ec1b6504d3b67fc83efb3a02227bc75a6b27fb849011211f1ca9420d4778aa9051851aa4a8a28a2daa885145156af8c11669104283905015671012aac2c9cf4f1555703b4dea81f48a74e895e3731cc7715b13f7503827a113d0e9c9490c37a736d4fc9d847a50bac98ef090aeb0239ca669dac391ea472fac48bbdec49d04e99ca2af59296b8fad42b0f2b787b085b245a1d852f9ec2be6704cc9b292b558f4aafbc3f7022b31b3e94f7f7a1717e5c2300104c8823925ca9f8c7d9f455f7a17f7586c45a1c8028219c6e2ab41b028fc8932a769505801935245623dc7114c8f2398f8d0b2d8d234fc01f138bf3edc93cfdd1e4bac432963b1954196a66d4ff1a7ca64ac628f8d84f83c1222cbdb47eee51fe12ddacbf7c16d23188e62201ea7e18e470c819737ec4cb09423e89eccc27e1e8bb933f1034826eec9d2ed1cf77839c20956fa6039858554301145fe2410ecac4296a62cca3e2d8b9ebb596ed8d261ba9db5cc64534edb08e6c48d442e3ac1dc237b250057e4eb88ad09344bbe3c4315c690e5c32f64f9b2075c913f597a8c4cbca59231c982857592e5279b1ce9644a7318e11b24da7746cc1ffd08d774474a0f5f463f5dbc4a61b36b234bfe7482fd642c0a3c205d9bfde73095c752e980d1bb4f64c95864c91f691748aa89fb44967c91ff64e9244b20597bbf5fca01f1c56347ac3ff7da0592cadbf7169b78cc631e8b3ef127fa449f289d897b4252c835ec31f7a48f0f40be50963fa5e03e0ef325def2e9c8e0d0077fb22c658cf664f9d2651064f90b65fea21be936b33901688183b6b3cc5a2887e0badb7dcedfb45376156f967f8c524a291f8ea27fc34c33a55c289d7a7bf4e8d1fd7bb66c27f2e30dac0777c02c3dca110c37e5c719bd1515f6ab403aa28defc9287fb3f171a00f153db90ac526b8b6c2aea0b8e81eaf4d370122153666e9397f9f287bc467e0e0431a30069541020173c3951823d44c29f149ee0f67f81f8edccfba3005c208e4e26234fc20ccc53d872d41b81784b7c4b8e79ff24189cee10fe34b9786ad7c354c70339ca44b0357fc6346f85be50f0ef588ad1aa844fb600298c3df251c82598cf24f46015cf18ff8836b981182ddc926d6c1f2b178fe137f2a55c41e3f9751d3273cbabbbbbbbbbbbbbbbb4f22b8bbfb4b48c3b9f676d1283e815864089dc0261c5c92473d786b8798f256103f96903836911d0a29bc21b024414763ff3904fb2366f85305e595ef01a32c4730212bcb73a2204aefd9362b12439f19b91e94e00b4924b1b07d7d9a4d586c1d0c232ba3ad2375505e3848eb3c492b2d6e977b3207c9c94ad92f52e5a5fc86bdf8af63a8ffdac7f4ddadaf7269f62f2ef72eeef6a63b7ad415b989f3115b4059be0cca52fa904116f7cd09cf4820d8efa70fba09b822bf47ad0357e4cf2e65bf47414e3f4f4850b4af27dca5b0fc8f2d24f6e57bb1455f7e4c6c911e77a747c1ba13ee8aa8f5fd4f284c933d7d1aedebdbc8927c7a4d5fbaf149d75b07eef02c9390e510b294224b28b26c9fae88faa897a98fc234484e4f13bffe09cbd037611a7f0a5fec8d29c544ff12c6c1d1be3e8ee87136179f527e95afc9df3891fc51bdf085b64e6449cf3df9527e5cc2cacc67b3f14c94e34e2990549e9245d54ddcebf6f9f101b4c7a07dfea5bf7d5c89143a7296a9bac7b5d82afcf9b708601c77df80239de3ee712f896f1952a104474711f14587102cf78325540085eef196fa0d047dc75f2a57fffc2390549e9a663265d8220064358c0eb8d24ce81e1d0dfb3ad63d99d7285efc3b46693fc435f07bc39dacf43d8de52b6dfa46c0afb8467bf814d72091a981313da04f033510eda07ef832fd980689c43210d2c06f9b17f7c960fe9b374c870f85c11ad6d1499da49d6f27bf0649f635fdf46b904c2c531f7e0ded24ee222ea29fbe4c3fc532f0ebd754fc6306c1f67f7027b64c0059fe29c896b03398812b0e8772c3b2372cb6fc3bd62ef873c63b8bb10643ed72d839d967bc231c824252725be0200db87d7c99ede3c38fdad36cf4b3b77969176781907bedb264d4ba44c71f8cb16c1ce662b61ef1eb1b417fc335dbd3afb80689ccf6b446fb883bd92ef4e743cb3d4b6c0e470b234bb2b8d0893f18636151d9b49039670fd7ef9242085b0b9e0cafd0a289eef6b8b31191524e78835eb387bb22287645d0cfe88a20306cdbb671dc155abcae08daa2a465c804070a2bcaf08a2037944aa592b5575c8103775c4186186495f7b6855793273370cae80d6d54a66b515879143421fc95f2577ff0e6b36d714a6163fe483ea552f511b92b412571afc88e7b11a523050f684518f2e9fbba0f2c9c821b8432cae52da6ff464dd1e32da84fc11d281f1f258524db0eca488e27255c915f4ab8d1899b433aa35c984bef2ede47302e9e2395ac260433f56842edc3b6b3ed70270a872de8108a3ea16218823bda4082d51458e16a9f1ec4b21327980d88905e24588e40d98a8eaaa87414e6ba93e36b149ad0e915371f94157e804e2f29a06f27cbf2b1e4f865aaffbc124b097f2c9ef722fcbdca6678a552ad4a1c13f722ae2f586faf1a9b8f8d19347858b936aecad7b8ddd3b8ab9f11e379b830fedeff942b835bb99bcfe6b3fd6cb8fad4d896bda55ff59b132cd8af94c3bd7e754f8f48e5ba72727c98eb95ddf40cf108ed94744e2f52506c21a158e5578fd33dfec61d876372b07c0e19954ff9fe14fcddd3ac3eafc396cb81b1cce3be4fb9fd9272e10ba7fd683e300d56a7702f562635567d684c00f5555f3d00200037bc141b3d5c1e5e0077e50370733c002e8df7ee0e7fe3eaf0362e8e4fb9ac87012aa729d8f8d30858abaad22a2b6599b10010b09f9787f016ff186f898ea78ec62e5f8f603b96bf07f281e774b5aa5641c8d08836c64adde54344d019ae448b233de709d52b8b9cc55a6c86bf54ce9e56f810c26a53def22af82b08b184b5d62ccb7e8062628c55ab5fa5067fb2f413ac8daa2cfbfa5c36ed63810a2a7878a6e089cdd018a5cfa67002012e814b96f8cee967feb413773991c642a7b768a01ef21b1f3269ebd0d3c4ddea1159fd38be00647fd83bb2b74e2d542bf5fe17ee18bd7feaa2fe7449443a476fffc5ec2f7d5a31135bfd8a2c22ed4337e91cfd2a13fe54b68449f853714322dc4d88e4ee5737d9be5571fbcffbe7e7e776ee1fd13784824d13f27c95ca5a4a1ae18b1560813c25f4fc66bf409ed0f389027777b8443a5c92a77b96ed64384348b431b9488b6d275329a0884dc419b8748905cba223b64e4fff476c69df39adf3402af8c382bf6ce863c91f4bbf7850cc320fd2dcddbfa81377b2cc5a95eaffff55aa2fcb4c5262bc50995c702831aea6f22f6ef71c8ac9858bc740b9f085f32882222cd0e7324dcb704d96b9a6411a6513eb32eafcfa4856dae3748fdab24722038fa087622bf5f4db27b6501f24a33dea394cd33dcae6e56b21bfa1ce43752cfe52b75f4e3788d2d4852f1e14978829f036f8194ed9a430b0ffb847817c00f4657c64c27a108da7907e8d9b3d8d7bfa1917e5f14dbd49f5316e67dfc5dffbe2e1a883f1a61efa3dd45f99cac0ee138bf5d0e76acff68aadce715744f6dc1ba169cf69b8cb70e74e5fa39f510f82597d5f7fe21e7d99b918e00a7d38f2201823e83cdfbefd20289f4ddcc1c09cc9e43d9ec459f4a32bc9d47ba60fec8ac3dd7c6ec3ddc43448e6c432a799bb186efbd59dd9474178745ebd8f6060bc8f624cbfc5789b172efbed65b2df7efe76fa189826f5a7a741f9ec6d9c982e8c24af4c8126f69f9f4c834eef79753d667b07c0970d77307e7b9b970ec6f632da6f9806098ca75179ed616019d46fab2b731c7545984caba7916ffa1596d11e8569e26797fbd3dd5eeb8ae0b8f8dbd7c8e7506fc4f6275c137fc3a777f19853b7b30f5f528f723b8b531ee7c5e3a03cea71548fe3e271527f7af882f2daedaae976b5bb5d55b95d1207c017d37327540ac5c50b55ca7d59ec3dde93693371211f8a37d11575e24ee4f1a0c8a2edd331f728fdb884f5df5c0867d342321bcf64ec44f8759691b2c015ed33d8aaafe14c46eaf22d64519c65d34b34e528a3fb44c1490f0f0e8fce4c94d11b429985f4c8492c24115bd9e7d48fad0dffd0be5fb2fba3dfd254bc81fd216526a949a2244a9a7ec4247e5e3d7ae0d08d2be72479e8abdcec247a7bbbe9e276f3c54595e0cba947cf0ba807907431611dd25b99a804599e1f33146ddc8ff6c15d529ade84bb22b4af6f84f675abb84bd5d77097920fade9674c261c2de9511e5ad4ff40bd44e168b5377dea66f6caa019120afefa26f53f522f53385a2df5f302714f9aa494b38ae808264887fa1f41e76932fd4c5dfadae3644f7a13ee5038a6e2ce54c29d49867ed59ebe09cb645fbf621ad28f0bc45952fe802bd20736e6d393aecd6ee9670f6cfdd2cb1cfdf432da9f300d12d3d3c4d7dee4d9d7c4a7b89b46645fc235fe19eea68b7753bbdd11f2c695a3b3c3e363e21e30e86787b3715a8a018ba6655a5669a86c6716b8d2ff90d53f2f4bf620496477150bdce1197e84303a04ecc7927d077771dfe1c68928e29711f128dddddddddddddd63cc522d9a910533a35956b34ae7859095c578c3514a29a52d299df423a55f679c32dac0a5e8264b28e2360dcace5f96e1d63f9bfbc6691a9c531003502652656e078d935280ad1e10ee8866b05ac8d20a593e0560cb333064a94596300d594a7792a58423984d66229b5265f7ece30d3293fbb71ba41e19bdf7c81f2ae1b93f8828eb9b4ee64758c8e8477805374842a0bdbf90172421d0be13627bff0d038979c4c35fd3beb3f621884eb42072931d7355e49c7d2cb27cd9c43df993dd08f6934d620aecf6fe3e700ff7e04f14726f286eb11d1103eb5aeb5fe4d7118ce631b03da2dcee17bf28d4637b3914ef9191086496b1d8f2584ce52d32169744987b31266964af9e8a3e91253febef9eeb6e8425b12d971c197d768fb8fe65f4d127e22f831b46bde6e29248148aaeeaf173847c19934e62bc54e22c291249d88b189630f9924ae20bfc6526fcd914fe54314625ee49f9924a248c138d60b84c899963773c441f3fbee845d8023942b8429f6bbf1f0d1f111145c0bd12599e91eb5f98a3be8f848899de1278e6bec6470122a2085fe8d5972321248fe8b123297bbfdffd21660e3f5ca9efe2df05728c3206fe3218f8b32b1ce5cb29dc935cc592c73db9c9973bd288b738963adb9539ee69b2817898b7742f3f2ef196955db7caddd63d1dc174b86df7e41eb12599384b3ec61f14caf2933199ab8fecaf5d1f6d58c68a60b5ff640c753fc71c7c77e22d1142d843c3dee4ba133258ee513fd89d7890b748d55b559c40bc8c84f6a98f1a47049be2e00f36f5da734edd47301af626fee342689f7a1993dac7e72e121aeeea6b1f7157b10c8cac0f8897392df5dc4dbd0693c21ee44043d098987e130a7de36b7765d5ae1507abbf0b9a6c179a6c172eba5b6a3c734efaf5679c73ce49f194936e9c68442a59d3099542712163eb458fb7a86aa6e9e4a0a45027932d9146226ed378e8342284c485397bce39e79c73ce3967cf39e79c73ce39e79c93ce4929a594524a29a5b48dcc39279d73ce39e7cc622707cd681ccdead60107cbbb61a3060d992e92056edcdd18c7f477c146db681b36ba9350c2460d1a33da460d1a337a860d1b356a746555af561c2cef868d1a3466c4c4204a75c0c1f26eb44a87afcfe95075d00107a5944529a594524aa977a32ba594d24a637c553dbc3168d5aaa683ea7642d0af5f69ad95565a6ba59556add64a2bad37eafdda5fdbf3706817c7d75bb38daff8eb8caf9555bd5a71b0bc1bfd5d90f1534aa28ffde22bb66ce45431de9bfcf4102c1695e444964eb6e3af1ed2394dc43db6cb27b22213b80574028120163a0ae01016837af076781aaa958d2f6779c45f0c2ad81831dec5a3126f7926b229d5ea69e42fbebc1d74f84f891c67721c8a2c1fea237272727254ffcaf11559fe2f1f1b97cd14363d39da10c951c8508e42e090a3cd4d8e36383966d6851a28b2fc29fe843cc971c67f427e7214e224472140f9fe27240ae1c9117faaa79a0a7f0df4c58f5f8134508e8155eef96bb713a23fcf9de7108bd1a77b58f084501649b27f4f93a61de34ef66fe92140d113e4ea48448b4677c75b8c784b7de771517bf68f4a1c6ee1addec19230fc64f7f8933d02658f658f4db23fed28cad17bee26d3b8df77cbb9c9f7c6f7d5f20d2258acaf57071f11215f878f3ad8f8bed46de06f2220ece626e377f119df44ccc0c16a380ad239c6f8cab1577c451d6e3f69a1c8f2fe01eaa1201cb79be4c456f74496ff2b83d99c9ceccff2cec976fcbddb437c62ab6fda75e32661e32a51e3ceb8e74fe3d200c5d6069ce5fe336e8c7bfef8cadceb43c8f3fe55aa17128a98a3b7e3d137b987b8e73fcaa24cc36538e211736eb20ff772125a862322e2d7a744c8afb89f545782429999e18847c36e6e728c7bddc43df79e4276a633097d0702e6faa2f70f22b646effe3d7cf8ff4822b64eef3f135ba8f7ef9bd84aa1bcbb787ff1ae7a9fef53782b7bff8ea9bc7ffb37506cadde61bc7f0bc11d3164bcbf8ed8facf2c7f655cdb3f70a57d3a96d32f6ebbb8283789fb23b2222bfee9f688b9a5eb72755cd1cd222bb2362dc69f4372fc6a24c7a737e24ec84efe8034508e6fc43d1ef7fcb32a32b19f95dcb46921249b16d23654931154bbfbe9c398f5ac53e45e7f94463a1f098a65762f42f7883a721d613e3850c8955384d6186ff95864827e00d1f116a84477774eeea6d587b734149264d14273ff06bc257a1c0901a93003119619a2c78f1e313e323f82080a0a2248668818991e436441784bfcfe21bca5003adaf6f09eb53d9a111deec55ae543f9d2bdee6ea9695aa6699acc3429bf0cb78e25f047fa1205c4a823e6833f51c70e1519501738d8e211c6160ed2f8349f2c9f8b353bfe547265adc7d5cfbbd24aa526606b06b2e08e986530e4520c4191e5a300b6b61564c94456750d5a1b769dc872d824673f135b9be339e3ac35c618638c51fb5a2a693f6f8c23184d2b954a5a2996de9f9a54583c497423cee3463c6adf3733eec121c71f4b76299af3bd89471d6b58c36a4c356c2ef98aa3caa7d2b08e79c36660f155ee91518b4066202cd95d60b00be4474aa9545beb9d4912951ee53994fba3f41f0c0222ea9dc69f4d792c606ef2ef44d2eb174cbec798c87723ce23d268e494f15f36c459a4fbf9c8a4f71cd789aca95dcf99d75d4334156cf10acff971887b92f430bb7c9f539b3f49cf71a449e2b47ed2d4b008b46e12a7f59326d7244dd41afeef0279ce4419f8cb6260184313fb4dc3c13df9b05d7e0b7503b917632cfdf01694970f2495515619854646419941f93a824199892d2f82bfbec15fbb34fc750eccab2bb38df7fb895d27fee7d85fc65b3495a11eeaa19e69ed231ec23d19ed511e8e808891714f4a9556d2b4ec35968c447c95d7fe63c9da4a0956e56147a8a87c8c2cd1878871cf15105f65262bd98844c41de9bfceb823e11f3a77dc67d9db640e77468c7e7b0790fa57bfbd4dd64ad0b955beafca4715bcba3de2b7d86fb12f57a4d9b36133c69427a9a229de2164aa488bd7eaf8ce90eb14711d4fe22db1e5aec8922f7e55f21c77b927dd95a50ff11c6f893162cf7197bb3ce72587534f6a5877a89d547d951f3e957d716198580264c1ece2ce5b8fa05a0d8b2cf9d049843014fc89b2ec3334a2d10e25893e95a7636b12eccc3e47303334eec9beb1b1e53a29961c5fbb99714f3e0fab13654c9e2f5d279252a3eb4293c8f3e94c9e4f9de7b399a1e91b6e3482d132202cd9b366c9132ba069964b2f5f017e005942cdd00c1521df5ee25ecc5bdc71c71ae69e6c58c75a59d6afdfb0f595fbfaa2114cb59d47263922a24e1ef135915f9b1259d52aaa686c5eb6ff5cc78bb8275f3407eb3b5e5f16bec46ca5114cb71d05f127c5e8f2a3378ed75245c2b6240605e12d90c65bd0679a48969f8be48893e573a6d10f1167c73df9d195a5ebb48e09e0ca09e47fad17b40ae44b1738bd88b720d4093222348527b99a4fcbd101ac18820316423fb48eee355100059c6da8d4ecb685490e158d40000400f314002028100c864362c16038266abafa14000f7a9848765ea048a324475114660c22c610028801008088c0c0c84cd50468d7a814714ab8e1010b61f70e433600f81b1e264287a437d4b6145b6652b87b508c19e67f618e5bb50ee4bd67a74db7d485cc23ddfa84561ca467b4829ea654e8971957b11f8c95e0418cbfe3bd75f096680c4d45950e1587077d6c3af1e208a4f12336446adfe15e1331640c03281cab104d49a0723812fa004db8280eda3d7b6078889895e2d18c1ae7dde657924541a92578209d9ad02f79340357047646123e3cdad50fd8557f192ecb5877781d13896f5c456f45ff9226fe3f09c6ef8adcf8dc084bbe7fc889e75f0250138e7342ec0195559956e613305652e0ed17689862bb87eb103d6aefb296a461144ff9db1c4d071feba713086f0d3feaea0d53dd8956ae6854d4bb148fde52bd101dd16b27f5bdaf1ff29e6e44727bd18fd6d72539a348ee3ab2b4a23c49884541f750824581eb937fab8fa96d6a947f7aa0bc57040bca39bdf76c1be16dccc5b2138aff0eed17909f09790ae424efcdcd294962b43e134d8c12f6d89c04f624a547cabdb9bdcc03819f1eb5f97b1b82b81202e213bbed124b74fe63e4347b6e9efe690e088f657ac20a291f5edf3ae45fc20e2e8ae0ef7ff5a925d96ed6daf9f7060896a22afd6c55f5838393f353103d08129275f9c7942ff16c93805720ac7a4a1f083246a0adc8cde67263ab61e87781f8fdda8b607c6ec4b07e818ad7e0a21f09ccefb5bd0ca400f25fa08045d4124e79e1703385d1d1eab99306644f95caf7e0727e6ca87afd4a9925262c1fd175d6e5ee9a41425f0faa5b4ffe7994e54b1cf90190ce3154347a5da4043edd3754ed135ab82559913f144137f9818feb9f86741797b0599ff39b7a813f2125d97e3aa84d1a084552050b7cf1483acab404535cf2c7f6b59709bab03cf03b9cd05b02b089428b4ef5eb750db2e9c064331ffe2e13dcc74bdb939162d5f5ac51b53d53d48516b387d240cab1d4939060401de95588d8272ec0550a42d8fc632fd0726a48774143c9344cacb84209afd0523aeed3c9c0923a5b2a94751449447e8cd90defc41772790059dbf3d70d60a7234219161db58e568ec5075238e1a277e646760aa0223205ce5edde8a423ae939fcb1f42be570962e982c42ef2df0536dc2a8af975c49adf7026743c2ac425d104d974832ef5f7f6e6cc0f8a4d57d87d73d704d0412f5000c23efdc8670495e291bfa0f4d960c3c1797d13d52441bc1fb3a761b06d521816bcd7252abfff7b4fcf2dd6a28700891d5af6ed05a472d38356b0b71840b0821e355df0a981c58cbec0920854602b17d20c989e7217fb9778f4b53fd392583a33cbf8c82350445f0fb6e7c1a24f8460b95ecce77ff5a7610b55476878e532acd481ade5cb9acbda1fe9692cc29e6972d7e15f9d7d29f86fba661340f8fb749c63c6ac180e1786ae95287642155212752e32cb1989f66acecd372dd0976c0140a399745b376f76218f5c76c83a3f9c6b1bbb8222a94486ad9e0cac064b848363cc6ac519c250fc63c67a0410a3ae886111eb3d81390091a2c70303d7df5c0b6949d0f19c47e68135fa809953be3c949fd84a32360c56e9c659bc2228d1028a4ff9e29a345c0c0b4a6ef27af34748848ea10e03f55c5dc7994c4ff555cb3d91f644185ba3842ef067542dc74267b60f2a641e2b87a444848f6a7b576963cdd67367eb912eabd603510674d28656d3cd0034ed4952d0a6664b69e20483081ded9128ef05beb3ef3ec33370af0bfdc581ea00412f700d15ebf0db39188cec0195fffe9f26da2c9d1cc89eb4ef1c92204a9912a9c212d0785bbb6bd4174631a14de01110920c675fe287bbd5de64fa03f99b021767425b316ec7c314759b701c00e55ea27bd00d773c5da0fa2b27defb6df3d5e2ed8aa0e9c36479a355cf8cba081b7eb38018631d3f1cb4410d6a4a9ead94fe0dd109f90aebc76f8b740ca6169329ac86a8cc62b1c06b1f651bb2446e6cb0dde07438d6f75422e7f469347213ed391fd017d598c0a1869a0258130325289e2d2362da1f1d052c68eb8099b5faf409577d50b4803fcc4bb7f25440d4211be747b9adce2d3ac91f609427ac90e141dce51d68303c881fe3265a167af5351ae9b8c2afa68f14d1a7cf9d0be685b0c9c6e74e15b80f695d3aed8c796f7a1ff589f395db714a0b86255826cbcde8e2cc839b3c44f547c7352f0c7f9a7849bd15865e8cb7b0dd8a73a53fdfd3ad738a80a25850a351f9936b55f7ec9c4a452be4cc54f3caca6062a0ab51fcfaf5014ee8c68bc023073a106c13913adfd6beb3bc4ae9d29d2829d2a729237b08adbb44ef760c0d1affc7022f26f4751ecfb483bed04911b46357bb51f26d04b5015c67f5ac025f94a7d1a36cd13953e2aa1840c312b3f15911fecd900e1233e044f0d18ddc32d03cd5251e0cfdfb519c50aca83af4b3b7d43f4df08f72a13add57c905a2dd033b7299dd56f1b2d7aed0bf04f730c165b10b2cd4409a682a98b013159d41c378ec13e62e117116cf7070c722efc2d0620ec5238ed0b308fd8debeb0725a1bf1115fdade499fcceb9f8ecf73fbeb0c0dcfbe62fa91162ecfdd52e13b79bafcf79b3f4d3a6cffde70a778d9d8b0475472c26002a61137a87ceb50b6d407f53c904c5bd7b1428a7f661d80c79b1e0506cc8d49777096e42134c7c57b8e9c92158cfb455e704de52f4b113c34bf30c72950d54ebad403bfa14062e3df85cc50666b2a56f04cccd4f9cbaa160559002e0a39fff46cb9238901f8ee020684e961d42eb0e20a8604a4e06c831fd7ba933cea68361f7e8543026f244b6c89a37a100e0baca0abbd9bf9fe4d73445b88fc462178cd6f446024038d520bae8895fa10018d0e8a7109a2514794c002c2fc6ae181e98fb6a1a0c3d56e94009ff9fbd053317eb90499539d866c998b69047b137ea10fa3fbd5523a723e5f75c4886d695244322bcf5f4cbae166249cf54f54200c184d502d91b6df37fb4fefc73f922457334ed8506b152782d2ba65bff3aceadbb26331d2bbca992ba906ac40763c3ad27d1e226529c1b647204e9d1c910b29b965d016a66d423ba5073636cb2a50583ae126abec329d2425a047931b602cac6f5d585512042e5869f6ca1d78a48e51b5e245db6e7912252cfc1414455369befa3874e2a8037a82cdd0ef7ba81e00dcb0e30466f84598f9994c0116987fa4352f910e10714190157f15823d16a23ff4bdba16c67f46fc4e39014c71a3a1f1d45c35221ec0382f1d1c1918f35750fb30cba5797a012ebee3de1b306e53e65b21e7cd6c84feb20da9d662bc397b22b90c130955bd540357573f2ce1ad583afb295e5483fdcfcf4a6d65c61fc8dd0d0a065b77c22a2f7ac9c7eac716b62cc2ffb966ae66c4b695a8fe63a34ebe386554322722fe83becf9625bd692aee6d8c21267001ebb409f5302702c8c2964b5a879e2183fe53a3c02d40a0590959388ecf36395de13ee6e965311e7b81306f4f20558248daa2b4ad42268dceb1f239e280e67ed12fa17c1dca26103c82201491ccae90eaee141602365c412e67b3c76a96f0b0705e05b070255e78c7c30c9a5c114c3930842d0df61b9845602aea4573af7262d321d9d2d977436fadd193c02750e654e67e6abe75ec3fa38e2e3f57b49bcc19e94651ce27068279fcea6533aefdac2bfc4ed4f0e82829aafb669679253eda165439660f7891e40c0a1e3e094b4b1baf6cc046ffbd801830b049f45dfbef88ab2d7f1c046906f9dae06b87bd636673db0024ae6a10324945f69a9542f321f294a4151699f85016e1931e729a091ef80109280156c73f5b04f9966aeebfdfcec31ad0d18beb0263333c749a0494e5088516f767e1062ec6250d7d7a590fcb2ad20d5ad7dc76471a7ee48d213d0a711ceda5ef021fd0223bdee1e03929d5e4534e82aafc88d393ba6940661b54957ebb01c0fa30c78669e24053dcf436ed717d2fd6d63fef0b803887a758f80edccad6649e94e269bf970403bbc068131ca76b6e6a8d8ca3d529c2ece2ec9b719558abb0f99037f6f41af9cca99512668cf431bfbad371917fcace72f2734ec52792d6cb2b4da112ee93f2c25507e139d1b65449f238107bffc986ce15bc1d59e6cdd894750da53e783ba136e420bed08bae2decf6c7dd8fa4cd7273b0294c53de492232c039317ef9365dcc22550ef8f1b68443001715a4dec87d874b1c9c1d50440997942ec6a29f3c90b51010b9f07caceab6ea50050b635dbdb717b5ae4f27566cbac6bcf92709535cafd9005d86f80ca9f5068abcc411926b54631ef4255b136d0e9db13983c5033ace75e8d1e6176f9fd02f9e7db596905e8bc583ca34c5ede81a251def6d6724fa397bb130b9032f250ee0b060bb6e3724f9974d1d1c5465ddae9454615a150f42c3d9c0b6543448faa2ca608729fafb9a176d1d656bfd9658992d3a6f289c0957d319f16227a3dd1644fd4b52e4c6de80e14494611a143f6f859c2065167b2b2493c1e3599b9f598b1daf553165c9bdc2c70418bc6277ee75538564c78684d46d90bd6904fad3573adc962638e844dfac49ce126ab492d7323ab21bc208c96868f4b6e325d57dc54dffb32a2209d9b6c1714d75831c2292312272af2213bff91e970eb8140aee051f7611dff47430222d70a06e45a35f489ed43d01d713ab1dd6594d00f1bb8fc29574b3e08d3f03b4e8a416c167450ad0f48cddbf88065fa1bd0cef11b642252ec965282146949a098f777f9cb0643a2169b0ea312bcf36681b5893903c34cda7d75f3809d594cc6705031505fb10d39b2ab3c9ce7979ed9a7f52074090b6956c0434145e438d109481720d1fb0341aa465341fa29da2360321f3e9ba0e7503560ba9f83bb1d4edee54887a635f0b89b4d86f0e7b3907c28fe39c731ce6f1e87a6a89489199863754f469c6c707c15489d442f73d08b1d8e2066ba8b14e18bccb15c5aa74a4da632a1f8ff9a222ab761c3df5282b359991e1929e9cc7316abd66497698aa465e783e2bdd84c57fffe5e88d7b915062d6f8511388b1ccbc11b903a647316aea581104e1814e187fef7824ab8859dc642f9a24ea88eee4243f6c845e66c9e0e76f0ebb76fbf3e906a854159ccf14aadff26bea616b5659e236aa5a29b27028fb0569f427478722616158de2ce5bfd6f416a11da18af5a11e2e11097de30e5561e17d626c1f442b8e39ac52b1630291fc658a32d71fdcc75e7ac489df421fce720d677f0fa0d7d1ab63f42b23056db21282eb9770c4b2de34000f0a6d058c1470c9275f962612100d3552bdc023b8206f6cc71426ebd9917c50aa7aee23e23f8a9f221a452d2f0d09971fa10044384f950970052b91fa1e278a96c9e1e558364092639980b998f8b470fe5b2d2311eb9e5fb79de59b85fa4ff835b349f9dcd6d486e211931306731e2ea67eecd73f64ee4930e3e912fa13f0912aca4d6fa15b2eae5873fa1dea504af815a7a53a981414a7c656ca0683155aa2b1b2f3e656d3bf195b3c55c222143140ce6997ccdbde74f983e451a60a4b9c74e10ed1eaf86df6654045bb257c4a3455f4771fddfc0985694146b0910a4cbfbdad47c82c76d655c808f5dca37b7d617249a33339e053e03c2b529f811b5aa9505c6f8e0c13dcb47e973099312bc4a559bbde6a345ed359027520084d510f465e9ef21709032701a9a05289e9f8b15f3c52fcdc97b580424e5c1559b5e5578302c33acd194d1f62ab09eba01eeaa52eebdf66381a1689380251f01bba95709d5e7a23a25b5b8b581b09c011898d30ef11a51d6dfc478efb080e3d9ed6a7fbd2624c8846d8590c0ad7799101463400ba8dd47dc4b86399276e67bd49564cfd5fe84de86aaa257979d23c6814a5e1a55aef0b7d34c18b49c921e9b3248738bf7146a4c86ae6ef82b0c1bb3aac733bec5fc6dee0bc286ecaecfdd789d54eb9745e13bdec8f11dbd6ff3d1a7df8631ff31214234775a01c026534ed4cabed0ee2ded1da182793e8e5761a3d80cb4f8f973b7f65792cea0add3a9b790f76438a57856db2cc2d961cc667001f453fe309d8c2a598952955a2855e7a255f80377043daaafb0e0b2ee7e2f68c6aa2e06c275e54a75260cbb632bdba422d4bff05dd629bc052bc1be9548e1c8234b3158ef494520a71fe983b2c28ff9ef1969d329057a5c88d6464efbaeeea6d42ff01def64086524ab1c393e17a1ebc32097cfd087ae15ed3c26277b8d78419190ae88c54b861f8bc227cb372c290aa4455a7a56b98c79734c7f6840938a4c3935566f916920d151a034edb60e898b60ccfe72f3784b65ada65f53d5f03478917d6e8e3189febb4935dad89d7297b0f5ed40502d9a3b659c57f1f478e55dce9d264a0906bd11e49cb5e0672d40aed589016332b321008c3bd769a2cc66eeafb86c68a8a76cf04151202c75233bb0f6ae2bfbdfca401e2536713a39fc8ef6c05f8c373639bb1a6999d0f5150e366e73b8d4bab9acdaad12a6ea0337121e41b36e06cda04f883437a4b0270cc186bf71d6d9510efec18b776e2eb1a64f36e5d4a74ce32a67bc673d9f50f990f49256fd549553aa4caefad321d13d4c4afaa5019584939a3ea98dfde4d6ac03d04768ca90ae5eab0350942e77562eb1619cd4b762e2fc92f54ed22830abbb8745fb1d417fc59c416b6128385502aeab7da80b483a003a01d93d55a1598a5df7cd25630fc6b3234fad9b7a37a1c10770a66186c0adaa844a98eef4e0a5c07323d3d0da5f3656750f3380885f0048e6eb00968f362f8c61c4e66e8f874133b499cbd90a03b8a4d40cb7bdf586e10251a11a9665ef123ed900c42380298f3602c4f58c591e71a0c6458be3b570c81d1ad321af9cc419bde5acf7a76c080cda093352119f62f2588107acb0d4f92d7dfced96d54cf712791fdbbf50603e576e91687cf54d8367911b7f57ba59317678c3ed6a9e15d375782ea0859a6a0721bd6885e0b95ce0874b81b4e6187c7d303ecf00045c7eae2086b841f1ac3200d44d0d9a0cbea32400bcb7003868b25b04839a0840d35fe8b9d7de2f35d4bfec94b8f687e62f22cf63e8c8e2700200f82e5d8455c162ff8f076c98040ede95e10ec85142fab70bda5682827bc4a407d786d4a10872851a4e74becda9c5d6a260ae5f5116d83401f58018ab525de9967356b44a224a2db7dcdcfb89d38dadf55d84d74e334eb61b4221d173f988dc1a6373681e16e0adcd5e663972c04ddaa6763c20f06eea0d5771f6c66b59f825ab60bf42ff0d68c2c42935548013e0c4697bbc108f8a5b70d0302ef4e9fd5ece4b38511007129f3b35acd0262e27c7ffe9870ba889af29d3c52771810b03f230208e7ccc0202c4e174f10ed04a1ad535f65318c1f39cc0c490168de0abcf96b33055ebff86b86440974e3456c84860e2f6a7a40b707070d647343c83aa175d03a6d5b36d3e21f2ae2f751413c7f3e8dd42478e0647d5be8865103098c76f875d4fc5dd11f6c1e5ae0bfcfb215f64c0a2cb509b0a0b63ab105435235080908ac88bcb6e27b75dd096d26dd87e25d23acbb6a1390c20135d96731a060feec157032be07b500260dc7ef2dc8c79408264fa9ceb0792914928258390c6af93b100ab30022da96eb1ae6ee7e17ce872f49ba3a87ea4c5a9543430530016a7280c972e087545bf853f8ded1884d3b4b454540f21d16f672e0d861c2c5e1b8aaac48ac868685eb1165f80803b1698c9aadc61058dcc6409a089feb1038580b582724f6d2c9a50874aa70908da0ec068fb9e18b07d3050ce9a8471462930ac81621e01af3617f14bd39f4f8eb5f8374341f31a8b7ca9236931aebccf96b24693c04a499c22f3063e16376ef5e4c35a12585568c863844f6b5dd3ba8e9c0b5117f1c2842b15a8381542ab1154bfe38e2b47b89caccd57e8ee310f6d179148f2cbad253317b7b779cbd5fa9254e39f147d413c8a558a321ea3e31301f935c75a3ca7166e729eabb603a546fbfc787b4467599815c4c2d8c6586b32a451fec6d56dfeb9d1dd246cbeb4fdf18609a8fff5fea7cea6d76c2f1f30a6d62ee17003dbc6aa2e17f1634162b36d0351739a0cdfe4a9fbfde6709ebe216c0751ed0cd238f11e01474f64eeb0ea7e430a409d709936a8d785b54297c7adafd37ca8d76f786e6852db4ca3b17aa85e49ad7b7518232ad2331af09aeee14a476bfb5d00178bd0cf84013fe0a7cfab5a5402b1f17fcd4e541579454dcf986feda1d9ecf49bd77f9e601ae8d69a7d9a49b86e93d9c29d1cd37105926ff4efa5762774db8047be916983ed4c7d6fd0cd37739b494218addcc6e2551bdfeaa4d64d4efe0c79fc233787a99be99447ab0113e817da99537c9e780e01384cb93702b98e1b44c15c75d9bbcde7fc70e7fe9e28afd5a515a0620e4aab94450dc0174348d4a6f187f70da52b53d32ca7899a9307ee18c8206e5fd286b92f970354e816ac528683c965b19425a397897241095771119206f71aa968b0e63750afb88a3bae8e2b2245e48d1d087c4c0a29f13329ca1b800c40af3bab2422eb644e21a9846db05449340cb3394b05dd05fffa1e887eed874e82d5b11418df9ced4793f2c7358631a637253afb9980300fd4e5526b1b950dad368897a87fce83d8ff557d4bcffd1b47c3b39a2ea368ff58b3e856985ec2e29b5b9cf5ff098ab8f2c785a5c691fddf9ec836db3f6708844a092697eb2e8715617265fb4b3df4bff9b90a35a9fbc1f66f8b1343ee3c95d6b7b4d5ecba32ea863ebcc3eb819333011a2bfdf8cfbaba108fea9f8a6cbe543effe9e40f9727549bc11ce39479acceac935c2a258fe05fffe1d55ed9ca85148d96dfc60541d3a4b61643d0e45b975e78d420d82f84f2b7960e68a45d33684cc36b7423a128fac46b917e922e55bf9f104ba637fa39ec3009a31578ca4392dbbc364c243e7656aa88ec62a8344721d0efc97ba6ece8a4b06598dde6f54fa772468d245cc7b5334125c0acf852b1e13011281e42c4a44eb3787743cfe7d1fb7e4123285b146e9c14f3317adbbe148bd69819bf25fbdeeac77db3f4d44db0c3619dc82e6d1651dd93a2f6de98ed8e03a0a426526588874e1f2fe84b4fcbd87533994be098ae1556de949eb32dfdbae4801f06f598019cf808edfa5eb139ba0bf5dde5d43680de7df67899deb285fa6fb66f327d75d0d44c45a7ef4350d4972b75cd283d2c02be6572250433e157d9b59d7a39802df344f796fe589938fe506a3e5098f51b312a6f6a72215b775535b1e6e07e970f880af765ce83dccded28668f771192bd392f71c3d2a85cd94442d325215c0f8ad35f087852dbc14bd6db1eefc8ad592cb0e56f0012c333f341d1ee53136766f728c3ebd4b1385e7d1a1999943cc14c806a0e52fd96ca79200d608d3c2bb4e459d9a841751377f099d3f625198f404807674a79b699460f7ee7183444f9283164730914c1922a36ce2be74ab1232ce3a0298108e337ae3ea2b363b58912d9b220f770c1edc05be2a5482328468d37713a5526ae07accac8cb2e95a82d99be836aa3923f1320e7e5b9fdd2e47adf94729557f13718ca20071989e3c8503c9ff0a0f21e00587610e8221885819dae33a835c2b36464f555064d4b8312622f28c3432dfd7ead442febd0340c13626a90d5774d55d38c10ff85ba40d3a0a137a25ce49c1323404fed2d70177346b61696d6a718ec899bac1028816f8e13b961ee43189bce4af2479c0d13fcf189c18aaffab26dbee4300848ed58348d07f121b21921497010e252fb6995c5222a02102692009a502974b3423c7d9c2047887288c0bfb10011f24da5d645ae828958bd2879d108fcf5e1895caf773e7c4081b46e71b213f8f9a640c76a1577102c2f176c500ddfba34359ba2e7e46722299d68881e4e7fee04cd8d9d804418e9d09ad833a5a0ddf4475107ea8d0483b3b0f6d408ab2d60863528e33ebc45745e8dfb5fd36a8d9e7cc3c49f98e8ad917c9052f06a85458d667dddf4ea9349b63fcc6852e575209050dbaf72d5dc3f0c6c2e07ca4b392029e195f96cc9b58839f4d7b94ea4f179b349570b1c7d555c91122f6ec8d7393f9aaed138d2c2afa871af78ea4c8841b77d5661035d0a48c7917133e5a045b016987e72707438eeef6af4e609aa7b6e58effd9b1181108a4ebc0ca38c222961dc67256b579b03a1b760d5c1650c8e6d940d683c60945ac7daa9e109fac71b7e3ef7419b33b0d389927ecb3da125257452860fab3ace2f511b5611efe2d06d980ce521331c7fd6ed0531750a7bdb51714f68276127254ee78dbd3c32767e86c18dc58f62afe78441a564526ccebfa3830a23f4cb02adf024d760ee3de71e51739aa07e816c4925456f5989c3b0a048d88e045c10b1cb7a451529faf25d60db4c372121e9eae67b2afdff50c324d1a5cb8ba06984341e388328143b1f2f0f2a622c8404c215ac4b1d372bc84cc73927dff0b2a5b9066181720acd23545137d2406ee2e2f46a10e2d7ac6c11ed02717b8f88659812c3d2f9889f52dcfc18031195e24d5b38be652dcbdd289721e86eb2623e8760c2ffbfb34490f68a3b2839f80f2fe8b78bad4aa4d720cb031319e295b0a365b0b1b8871dc9d1cc0181e0c36ad59054196b0fc736e8fe3f4a771807e2cdd6e7da08d91f801230a973f7820e20b505ecdd1f40bc8001d5a1ff797e5bb11e31eae73de7ffd30dfabced1103f1c802e71544058f37f4580771b0830bc0e09bedf222e03e0dfa5fd76a880b658734666d5b68eb06e5b1bb6569c28ac24deb9ce6bac73d2836aa58b0f8192baa47b6d006a057df2167c53714773d4b473e382f6bf50a0b3e83c3d883c6e526bac98ef6f729fd47f996ee35c0b3d263cd221f9937c33dec89d0e3960395d132fb6d79babba76ba9613f4be49d41c340a545766ed1b5324241ff0029cf14913cfa04158ba9d4ad27827a07ce6efdadeabfbefb3fd4243b6b478aaba04e522cf574f740a1580dddc768020e9240d99931861a5442f46fa80d34b0d23ea74472f026727870a216c61fb2aaad408faf8c82723ac5fb42c5c6b543a3874718edaddb4853488225008298c7715e388dfd96a0ea78c65806ff0d2c0ce1292b71da47b487ea089ca14c0b343ea5df42033a888c77f960ca6d9e8a77b5052abb7685b6adc95b2931922b724ba539733761b044eb24eed950a7bf08884e59380f8e9b87b45b2cf11282a930acfb2438e75715ea00b9fabb3f1d32d37876b3967b9d19c20a6491176c9779ade2f11041d4a0261cc28923e36af96616b27e0c27002b3a7b365a2843482f2bb6bc12530029a82e849aff075ea9ee9bde0b0a495c5ff2270dcd3aaf4ceb1d930dc85cc021c655fc483c80dc6c4f9cab1bd773dde02e4648d0d8c94ed0b520ab6f0a893c92837ee81632a72730c7b64c828c639a807c92dc41870a1d8b4e0437e871fd387431bfaf356b26bef886fe7857ddf97c2dd3ae2014a6f2e496ee1e078dd3eee2f0fd586395e7614fcd34fae0b6f969db9dd1b35e6f10097311ead7fd65e92b9d4f1e5c4ca2b77fcf34ce9de3c811145ecfc0cc7a186ec18e6e98726ea4db6e95f8183079ca7f4bcaf044bde37e379b33de621ebb8a51a98c22bbbde09c1e1022591c58fd81b5163d9911f21b621e4df1684a06389223746b1ecd397c262513c492b156835930d39917917c9b932b26d6dab0ec83dc47e50778e3c62dc04a79a4089664c0026b9522c06d5c45b290dbe9278e2cfc1d340e9f246d702dd6c19af68affef8a9bddbb37b01c648b5284f69b87d55cfc2065e75d6a006ce471e7ce03f344d14f621347d1e76ae1f7d58c50132dabb16e2364052d9a866c0e524d87687bd190017fa7fd6f8e617598c5e1d36b0d86fc904354eec0695047c0675bca5519ed9b8c7a8c1fae3faae64f850b7833163202267f70e1021661ee882a678eadf6f4bf85522e06b9b6b7ff05c3b38e9c5ad87d6dfa36a69294754af4afa7150825232d01630671dd2ee033a3e17d95783e8f4412bad20ed3f14a00ff1b424cdeb94294d25055ad842d1d22c175bdc14e39d8f83bf4edcd8879f70e1c65021686391861cded27f8a66ce8d485e9772319d4357a733c41d2ed8481567abc5f407c7790a12af581b76284f798b3acb96a6b302ea8261d1328f1e62e542085c13f21bc9805e3b347f34136481bd1ba9731cd8bc296ccfda35c2994b48df931efb6725681fee68db631f56498dfd8aa952f41df020c7b73c18606217b86371ec7dd25624bf6287bcc83751c6c15c85ae60e29e28704364a808f089bb77e01fd95c45876ea0fa80b57a0be64a4dd9aadd87bdee52c5b7de4a4bf39ef9af2b9b814abff5cf9fce4bdc10d26f913fddb058d56d132c7688e08385dfa0636417f901f3e49deac087f91fbd63f89928f0ecee1aff0674ae011550a14426b8940afc99f857a8d1f89e96b599fe0014f621008fe89bd815603a0395a3c6a6dc40e591517e508212c1a4a411365f2c95876f0a9d32c4c778912feb25560c62f03e23bf82b7e55ebdda16f7b32c1962d987321786c123ac840ee700b4f5ecaea6e65b43d1e8a41cb7a16a4c373458fcb9a7494892a445470c12d8efceea4d638d3944e25bdebe1144cb12572dc740a4edb660bc4df79ed576f2c1d2ec91004baedb702297fa20c983e6c85bc24c59d2f586e6f24ac8b608b8c18ce92c37b8c7d2092052f28d10b56648f50ab007d3c263caaef3d8618d885036efd27607d664c55ee095107b161b25ff693c1331c75fe8afdb2f0f09e4fcb638f8e848de924ad489f68388e52d96dbde3110593e8de5b8912ac25114bce2b95fb685e3fbbe8e64e422e46ed9dd9108602805e8ccbb6a3518766087841476c987d067de13b4cc59fec17802e049a55722ae8f68c0d4a266a43d8bc462e4b927ae1a6abf2da2fd83b4db311685aeefca998a633d7e819ca124fe24dc88a6d17a01845004229136db85aefe1519632c9cd062c4888863e77db5a707399b17e11bba720a0309cde2fc0004317951428cceb5919cafc6239d44c5f31d36b24d2480d1dba03b91a84c32864344be29c920bc6726445a581979d2af3bad1289e661a0d44e740e5c7dcbc30345f112b94a23c7bb1210bae9c941ad2fc3142137b81aac2552ef82ddd27702d0ed1b3e6c918c114144d603384ca56dfa077a833e8ac620da47b66389a8c019a9d6df7538bc98616c53ef66cbc3e6186845dc4e169a1aac40ff3507f4c2b53b2dd4be52aa507b2276d1590cf5b93ffe1a125c88d18bca955d242ca4459ad6cdbfee19576c43226c9923207dd750b13935005c80b7ede524755e759dcd94c0b59ef04a7b11775e603ed118ddeb448ae07dfbc6f6d569759867b0c9de3825d4021ea2913799c8b66e660f894307f5719dad681e0d90413203df6de942bca0155d711a4c538e04ba89486862a9d2dab9559cc27d06583a168dd49ee7b18e428e7286566ab061a6561eb68ac46978b1295d26ba25e53623d0b3057bf880770eae2b8c0de7483d9eae8f627c2765cd2fc35de2ff5e3281903a922d154a3d16152785111fdf42e7357f767c94f09c8f3ae559bbb460af99bd80833b08d2d93e8739fcb2f864ede2934ba958cb7dfe61c70e8007a79deb66b2ecb8b8e90ab1c6ac4d38453f8640fdd2cae17b9829fcf5c2062f1b021f0f16708c2fb9243aca1aca56f44c457e848982bcdd8716b13381b1b65ad969d55140710781a8b07c52ef9c0966c04a4eb0795831172f58803f533b1a84d95670480ab760e7d26f2d34fa023dc6d1c0bb4426003cd7ee5f53e7fff3010cce8ac348df3c5127a769a82111892d656728a1a66839004747fab286e9992527e5c43521bf2cf9e881765c3c490ea120401c5cd1a6067337c3c939212c1ce6e40f4273975540da24c6a7714bc685eaa6c9fb2f57b178454b77abaa0ae489aa7ee9cb8cfb676e6ff68e65fabb0abba29050de0ac67c42cd7069bb10cfa9af25850d68c123bf89f23d734457ba58fa28f4e4a1545041ffc0e8457a47278506e0543ebef3a38345441326da0acbcd7be25e4e050be08df5da066f518628bf0b30b25570b8cc315210cd0af3bb9e54cf37b82cd49d7c614270348957eb6bd4f333daac9df33860332c33f9a47bf40cc0826574db9854ef626dba1f8e9c5afd1bd8b5918987e43e0f5018110c54e42ef9896f976b9a10861b4d9d183969f12301fac78ca0e3b4d8d3c1858b50f536c3cd3dc82c5d71a985826d7dfbca025e49ae8f628bafc8c56d88c26a65542202c80a8a6f50b9156a681fe17d40f97329ca4897d9410f18c39bc4d9d085d907f50572572e821de4d95b8871dd8f864c287453c975874083d4f216d341a313a03f226c5f570ff19a1906eabd65ca293e63164f6e513a5063ee1f7dc81fd903aed6369130f1aa35528fe1ed4a5290b4514fadaa06d28881b1eb7e548ef9e5fdf9d4b24dfa4ddeeccac49e43e6aba3874cdb2563c00dbde117c1e788f64bb6c7b1272b8fb7d882b58e58d59e064eae46c3f244aabb4db145c01ba1f867873286b237067e274a28b86500b6782a5a1c268c8846b79f57f74f2211f6f437f9128ba068fa2fbbef36fe6dca1f332e1ca0377fed8e8c94c0ba63fa888f574d5b544c7923efe1b2ab096429de30b9dd6e0cd7e7fe8bacf2d4e27bc60ff7586ba9efd36ba5df562a380e92c383930f4e712d33972174828d3d3c3662c59a4fb0641a2557b845ec8af9dc21f024ab95bb6cc8e0dea4bd0428bd24e58bfcce1dac89d7d1c96c1f2f46a2b17d644829ec5bbc7ee6d24bb01a2ace86a95ff5466ab537d06ec953fd4f7fceabe3206aa8603ccbd24e30f8dd42c18d03f03c9e533fd98afbbb952e2eef61f8e25163b1673022c6253a013715b856b0751024d373f75c6d5ff092acd557d1d7e079ff8883deb8281351bdfc2a2041203fada9cc8536bfa6caee8e821467894899540e0e326c8473481d54dc998a025ff8257dc94d04ef800e590add143c549a2b639c5544606c18a6e5d87e37992248eb268f7b5444f4be3af3ac4c26b7110febfe487071d439bb0052be04a8c82bd64a51529244fd235e9cd9058cda1152977049afd2fb359942884c3c071cf758a89fcd863b2b6ad6ca928fbfa26a99c8e1f148e1430f9593d0447ef1538a2fd05713bdf5343119f6ce0b92e0bc6b58774daa0f8fe2af6af298a8b7c1bf821bce46f12fca11b36116528560a41f18fefc7b33a6402ec472f5f82b68b986265301c29cddce443bfc620af4add33aaf33dfeb1fb7a133363e33fae07ba92df56f123909601067607deea72730580ef058b42bdbcdfe107deb56cc83a1e642bd3b5882ba224e499ed52077fa17dcd7d5e0861bf0e0244739cf63be57f7192d89415118777183bc5cedfe99b6efe9ed01afec0c86c4653ad19bc401c2268030d20620b2891485a721d66945d03d5f7c6cafa2fd9181aefd890ee40c3ba7b01bfc79f3f137e0f142ea0ce7bda13703f94cef654244f12f8a91ae4b755526972ba0dff7c7cb2c6273b68929a8dafd8f59fc6de9537a6e4467bd6d5612ab2cf63e530793296e23b3c8f92290adb38dcd22ffd2ee9c73da604c3d19e0b0baac95730693204d57480eab580f23c15432358e2639724cb1894bddd33d2b6c8650a5899bd3ed995436ec638c6e9e4405329c28e2d30f9874545966be440628b8c1a0ccccd04afc13e159eabd7c296ea1cfda387bd97022ac6dbb12714f77e3183f4bd719b37c2a9092ee25daf15ecd3ed51fec3a25eecac1c8e5405b56eefe8c913b081588d2ae8a9ecea71effeeab01bff972af42b6aa561e1a3fb525c3b13d405a1b12f81f21f48cfb8c1152ee3861bb54fefce1010dbcbca69ee340455624d06fa46e332b5dc20ab3cb05fc082e580ea8a23f24845f87dac3d6a4dac6a0c6b97e9accc2b8ae08a19669053e30f5f1380a899c27c4ae05d2783e93e379c1faa417e758a729bc6e80cd7c7eb40b2dff7a46e240fa2bb7f0fd5e0d11ba0b809cefe0dfd9daefe5a585b6070225caf32af0814f7f7059d9e8d6e5459b97148664b8347da66104f002f2ea4eca6a29029a8167d59cdf14fa9d6fe9b031dfc9d2a828e2d4cdc2c9e7f0c7441d0c78b1c14f05c6ab0e5eeb41d145e406b18ba24272a4c5016d0b05a9b8fd4dd7809a4578b93082dff8c5c013719fc9c8719ab9b0ecc0f87c1b4a64aa621882ebcbf73aa081b9a1e62909bdc0da9bdd830f9c1ee9cba2467c2273e73ed6fc9f36891362ee6d0bb40cca2440a03b85a377132d5024cd3df606f16217301075f3ad4c6c8cc85ffeffbfac9b0ea2317b31daf744e3f5ca6452179c2361522f3630c6dcde2489cf578bd194ff412c6d1bd57de329611cefb32e3c9f5a7588b061d3c8024f368664ca34529a7fc9d935dda29f46709d1de50c03355e77f802304339bce4f01056b53919de2c266770f77a86f22c7d13b2931305f4a29f79295bc2da53c2f1c3fa3fa3c18f306ec195a63c0f269f3c5be0997021a1e5018649f603f87bea1d146db8fe16f235580755e0a351f28672d7dbfc728c280eb950efb30cbd6a24caaf3cd062d4db8f0584cc97e2549fa898ad0fba60b6ddcbc3215fd35b396b4627fd04020f62f2aca825b9172847c29d354ed67d9a325514f78d0cd8ec5946a6fa7b1ce740ed22ccf81c2ed298c10e25cf20f2ee3b3f616e01f6a018804d13a5e3c1e23c3304d047b0d69c5dab541aa3d023052c114221550a2d3940c7e3412b02ae548695ff00163670dd5f9f0ac7c0c4315fd19fb8d290098b0d307350bfb182f6411553c84cb98d8ea28319117ed24ed52ccd97a241529d4ea1365f554021a95e2006bf9ee7c2e7b573ef74a55225d53ea95e85cbfd0a302102e9e67032e9e4d33fd1b78feeca86985a672a31a0d011da6a42c5e10804fa6ed3f9fd2278663e830f068be37ce7d56ca0ad0e90728e3c9747a5c2f4ef938fff8631c49c1d1a6f2aa3a6103497ccd547b222415f591cb7d189c6a953cb9efa67280cf2eb0eb5e53104641816ef594ff3cc0a029250b4399e5244f47d49eda32a8313eec1559b1a1699549230e45a759f884d26fca4ebe1fdc1702b3e0818846a35e46591629ed3dfcf074e9dbc06d2d5663852e00b9276805df1a409836ac752a2a8e51ba3f897e04bb936c3e250d8d0ceea04d90e84c80e36d633638cc1872d8d53d13aba7dd8b55621836c6b4af88c61e83b9f3a0a350e0801b1668898eb2b141529c7c2848d0f42f6f2ee81e1f6581680ba0451e528b35d85d0025bbd787b4627cf76047730a12c85dfd4f8f9a239b2b867582d6e746d79e128ebf66c7e44a16d32002536af1b1cf067acb204460bf4c69b8fd5906414816811d2dee6cc6f3cb1a57168ef12776ca09488c5c88dd014d5ebef3ea2d579b7b4a4ec0132cf9d6f60671f2b5a088aff3673b2363358f840f0de240afb36fca5cd8c0904d5c4418ac1688eeb9117c05caf0f2cf811a440196bb215fda26e9b72493889b1091f9c744b5f2818d1c9501ea423088cf3e08c4d49c203b249acfd8162513d1046cc55cce56d18dd2029877d8f725c0010e33b4aaf1a10644eeb9fd5362502b5551c5854b80d19b09f7abf88b729007dae4dc5c0cb74b3521309f6a083d95130289276c59cb3758d07ec4f9d1bfe2f44501c1dd8a987e34a12b0d8083947ba305d7e1c4b86d15e2555c00215d8c8f4dd05e4d828230a14626f07ba47a6510168b93a3ca166b1d06bc4c6e5234d5fcd6aaa42433dfc22ca562b5837a45ccc05cd8a5b11628b1c38bbbf92e3315d952486e752b10584aeacce0ee34c12b8d3de51b2fc568203e0580b75b2d70669e3205b65c15fdbe4dcac02074ce41b9ee3a18edb2c5a4436074c6254451661aa7fcf174b69552c870866223613d02d4519aea97fa1ce16b7780cf94a0a16b503f782c65b3b79ac0252da077e1fca5e2e10f5cb2a096fcb580b8f3c510b68164ca1ec84a8755e4e921d7285e649e3d2f270c8777fa6d0d126f6c04b671d8a95b1ce2895b923ec9af86ebdf106cde8d31650e1e6c2a8f343dc2a6d441209cfb8881294265ed43e386fe2a5ba8b0a285d8fd0ed60d38ecff4474f370da5a7de03f34bb19dbb954db674055657c12f66e94c18a9bd8d8a57edcf58064b55334147020332a602a0c795720e84e335826209bce3c9b7e6a01ca7659934b1a6cd3b038c0b0afdd97e46da39f6b23f98c27b73d4fbce93801d227f9d6a839937acb03b2eddcc96d632fd9b670fe85a6c7c56b6440b867e023551907813dc26efc4b74895948918841e98fff5b126fd37da8e9c8faa0140611101f3ee0e79214f62c8cee65f39f967f87d8131b355a7d06f1ae411962e3285bb886a9e0cc822c55c4264e831770a68caa5db09b265590b5f6c23e03ecfc7944037011eb8a3440de59a5768e4ebdaa7b4489b9577bcbeef6225a3b69fcc1bdfc3855fa97e88b332b26afba99fbaa11529618122d7a6647782cffb2594272aad96cee0cb20f240923067bb1f2e2499797cbae46cc823ae7f6b55ac5385873fe61ae092941a33cae8e08518c51ec0f961a9bc1527670692ee03e10a51c061a76f610440e952d3c4de41091a38e43c209ada273fa01836b5812ef058fe640d219f4a2b36c7b905cea78503ff34a053735dd8d55fcefc9d96ec826c8977b831e620d139b009c5b2c435654eb43b08806050de15d05c988f23e6c382f3b1c1a2e813256a2eb2534294988ebb8f86efe99cfa60e42f51a573ed22f3538dae0c53dd5df5c40916182d21ba204ed8e88d10c9ec096ba4fe6b781314a35b22c1c8eff2fa560b469199940483740494db04c5e03ae78606149190498465dfd680f1d2bb959a8459e2863bd05f65277bdc43408bcbe168278fdfd7b9e5e49fc3ceb0cc8a37e144041aecf2862d603026a3a2624f845604ebbb9412be4a35204bd428565e6cffce43e574058792ef809d1a1f2d7656a003d6366126b1037c59ac4cd620d319338b3b821c62466169bb2fa9a67d1971cb56cbf4d310631b398214696fd9b216612631633c49bc4cce20c319318b3d8940dbec8b664f691af12779af5dd286e16678a99c54d624d31a358a3b829c6b862a62d31529bc18c95f095ec69fae4ebb39c3a8b5a02d76235cbf01578fa5b0facda7e20dfdaf243ead31eacebdb9ed7e56c023bf830b700e76881cd7ba328bc2ca41279612fa7c567387f201762eff77b26cdcb47270b7949838b738350d25d412d83ee69452dbb1b39ca14bb45d552fc25ecefa78b9e441fdbc4d2b0a9063508f6d1b995a67628e520f6917f2990bd3b57574b3026c61365f81581e487cd2a8e07e83108234358991d811c0b47601123830cd80c9607aa0abc3fb33c38e639c6523870d331db0dd05d6c29bb16e25bb03f09698d2de4a1a7929f2afc815ce7f92bd569e72522b4b42a33c55aca20dc24396218af79d3c0ae54246f4fed016da9cb55cee266506a5d5639f3b408d191567a3af57bb152f17374df4289e5efe4bdd44529807e343964fb0c020ee9cb8125bc04c21fcb3d26246b717a4c984ae3484fade974fccf44daa4e8b15d340313748492bdb02bac22f29e1530b417d2c425dab4f4eb5d20b2995a653d4280b69469dbd1f83999397d222a22494a81741e866c9b9f0defb888e7f5351caa83b688a61e9340e63e7ac72cb3670f39444b6805da3a21313b8eda5c3f15f21534218a939dc3ec6df456d541fe6f9101fef1ad2cc46e96127c9de780ccc74f2e6590900fb1bdac1e48c651ff302007dd415d8c6cebbf3d55d3c932766edbcf8665d557762eff4f68e4f26c9f7e63ef8127d8bc5dff9bc9818630eb98871c296d4f9af2720f281c2668c46e800b83375c00e609251d36c47abb04cb013339bf01c7841c901c5c6af5cc800a422db30f3e09045763e4f09e1a5a183a688f733d8aac60313661ea74d8bfcf9c43e8a2bf74772c785e7fce83957c13af4549f010aa89c4754b32706921541fccc3a4c8d93584aa8d66cadc1d5127a9b6398290c331f17ed4b1ac1c1037920e1983c92515bb8b2af1ec4dca82e6e1a70fdb6d8daabc279ce02c0d9ca22c4530c07060ea9cf4b0b58328ec3738af3fcd6562f143c7f811c7dff2d1bbf156f6346e5def194ab8f937521e1bd6000d5a6bdee2a12d9c5ac0992807f1f2f5a6500e14034ebee607afe27fdc8332087b940d573181483cebf3ae6a6701c251c9f7b7bb1441f1c8c312e92223cfac70c3aa17580161638025d31f6a321c557a9c0af9fcccd0b577dd4b6151d3d34a1066e68ed971cdd06460a1d732eb07cc67055a85234aab1cf502ecb416ab8d547ee7286fb34c8e78752c9b2b5ad44c587532b334aeca82b74c418420cb6470ff82d2a6e7f8f9eb4037705fcb6329d6f8a1d5c366d6e5d9c17d7439b6d42177c8c6cf1d631b86c05cda7866a6bb917f27e32bd5da79a2a6e42ac91c5df87b59b94351104f70f4c914ec598d5551dc193a4723d938c4a2cc205df0c2c3dba0d7c9d27d1a0de78d6874d7d52f5b01d3a605e73a7719c98412c07ec6f884640c90cc52098f438de6318648923e06ef32bcd0adcee75ce4bc417d0e0d9ba5088d3607fcd83d04b9c58927e5c9a8cfda71044493fb2bfd7352d8bd71bc80b6470b6fa040040e6d6ab1ef203a0e9d0344d90695bc48eb1efb08bcbd6c3f59b144525fac1c4ce6a5db015b054b84393c78f03380556aa271794b409b6e90f71e6c22d28d1b844dab2792ef8c5d97210bf8258e1ad6e23c52eca17e6a2acdbe6130943c0fbddd1391cc418dac0a610f2d7fc415993e8bb77033dab2d93a289b0011df2c2f0050d492c7dc2390a9227025d7aad61bc6f353e2f2c50c7b734b9862ae6163503105e27533384520a239f124b08802d7e204520e5974ae8843de624c68865b259fb14187437c834c1ef3173ac86424b26e87233debff7d201ac24b7e3485412156cbd403510850d0c11aba52a479662387cb48cfde7bdb6d582233c8211d2783301903a30e3b46ab07df438a6c5889bb553179c96d7bf0dee83089232449c0a5e280802b7452648b40c898f3566f710b5c6b999bedf6a5d1eb74133c5398db53a7138e57c7a2168ee7e07b3f313d38bf5e73a76b7d460892faa8a027d8ee40b3b5817efcc41a7bdc57313701077da44359ffcfc93d56c32bdc3b53b178c855e5a73bb530d01e601150731b51d486570848352e7db1c8d8a6040dc398724d4b767ce956871c61149c7d6ca18cc03ae0e2747416000b36a4127e699dbc204f5c1c83875c85c2496ebb3290c8c143a5c01aee4509909bdf3a7bb88cf5f0440bbaf4e1fe9ad1d5bb2c7b644f2e19fbbb2f95393e6bf3ba8e2b7959a135b5bca59bfb7c8e5fbb8cfb0140965fa80d7ce7ce5ec32b16a1fee2472c4df31a01d5394f53e1ce09cc9704cd3a12b443294df8f6ee1d41bb65dd99db30be6ea874e9c8923c97b79d0da8ef7d4b8a1d16d8ba0064e394b02b553f34c28402109ab953ebadd3d0adc27e6c844ecfd4fbf27d8b8c0bfc447a8224b9c23dca144a58ed2e51d87de2f6b39b70cfdcaccc97062e3fe92fea7280d8a0d3ad662357436e7e49e37971c8bedfd1b8373843e205042e6bf3a0f52742386a1b35db01f8c53aab6b99b4eb5926db92c81c7a93ade62df37dd3cffe7f6058f06e0ada371ec716e1a56047308fd2424aa37d604874dd87220decca939ce848b6b792f1735a4549a175722f122725476e201261c6d42093259ecbc1f4eeebe231f28521af19e171e4c24a195570250a2c38ecd2154e65dcce26970d6f6b10950a19d16880dbfb605ec3a648a66ca46ccaf1789d5a0a04b7cf15cfc7bd077c7ad57207b70bb51b58d7497e20c196fa097bd7aac1d170e55f36b60ca8838309901958f2a9f005697aff26d94fe803712e428efde16da57f390846d3b54d93cd21b60741dd4232d81772518f196ab819b0a40ce0f1662ce6777f849a902d9d2f2815eaf41bb638159472d603f8e02ef03bf4de5ebcf7ba4856ae1c177cc247908d66516f2ec2b201d4d77c52a2f026dbfffbad87bf15fcaac4262f0eb6bccd36be642687685a08a12483cc07189e8ba6254bd7e3d90c43d118e9e67408802c159e065d34e5d31cba88a4500d99a67e260a97b0e367e818cfaba15e0900b42e3870298b3265172a0aa62920dc15a9437c62a3445321d648492e8fd69acc8817c6310e8a2502c6e0f8a5013a8697e57fdd1516f9743d8d598b0290a7bd59361e1ba09270776229c45554922158af7de5a879a90157dde1a2a87f8b0e946d4a60dcf860d2b2204ec45a7af50cf6fb2a7977007728b0481a7c977df35617432d21c66e4f71cdd3112d71b6523234d2ac40e89e607a521a9110dd6998d4d437ad5dfb30fefcde61cf86c6cb4c72e1c9e9e6ea0ca652f01219f9b82f79f9d71d6d8c474a198046a775f559f3b2dbad46e8ad28f5505c056f3434f2c47be472724a809d1f65dc2f448d05577ea18e5db7c638b7f66ed4c1167b7c0b32c0fd1d5578a885776df76d1006b8eef45b4698794b6b2412cf94e784d8c29d5bb0d1a6148648aa905cc6251b6f860b302759b6308e0468c16e788833d59821582483b563b3c7133bc29c163648e02f8b45172de40dc909b9aa956c46040876824813be37f07528046dfd4794e695ffec399f3a4d8cb427c2d12046eddb48b0f72a39700630dbcb399de9ddb7e913e8c1b819c5305a6327cc144cfbba8cd9060b70aaf612d526c0eb9100734802a35372223cefe607357ad63ad8385e08d41852e4ad3ac96a048147b8b8df4845264118c5830cee66ab96834e9de0eeba2c5d92597361f77ad5e9b9e6fcd95202e2585c165b4319e7b0df0c1437816020453c69a439ee4c3d2f74fa12df01a3860ba69592b7ce5f36a950c946fed00afe3794275403e6b9c21dbf1f22cf88ac10f61a1095abe144dbcf13139b2122e9244570be16516e18299d7b576fae2fea6b1c82ea72753a227b300febf463192ce8162dfa292da4d11721d64d233a500a405e0e88272ea653de933aec26dab7204635a3c10d549d2256e783fe8c1611d86d33eb1086ce56e23f585f5f838832de89d23203e2c487025e9e1173c39cecccd5a72021f251c8a017628bc22a849c77b3d6c9f78b5cdf253a25bbf1da3d6abb485eb5d488d8208033b9086ee4a7c8945c0145d0ecdf1f036dbb52990758dd7d997c700216826f83a752cb91c1a8927d6981ff93f6d4b45cb5bf0e17e28708e574c95c4e59d033f1db94868a9d355393e81dc9f4c2876dc84c1e6d401ab876d6263e3d29eb30e7a84144ab73ec66844a80035b4fc4ffd487371e8ec0f224b8472fa5b728efaec4094dc9948267b774a77e665a0415c5a7b0ffb32eae0de21428418d6ec97d6d5087392545587292aec6c5c0ceffe25a37f39ba5275011a8d29cc81b00017f13d20e746b42a39c21f6750a23ff0b4335d81efa5ebd105a538db8e7ef05cecb84d63c2f776e02ec00881ebfbdf314e4cd11d316baf9ce00f31674915e4fe1883e5fb8de36ae5005ada5f6196bebe8f96dd48cb31bf45d043c91b017e725ac6225b7f933cff8a8c3a8fe36aadc01dda2a3f6eda56f24a9dc302d1e1fc36173ba4b362bc02784eb596abe48977c0c3b55931ccebe9f4f5b4f328851cff9c510de81dd88bc225785e8ef12561cfe17cd49a6328d2907300acca296040ad7656ed07f2e595c72c6ac44fb05f1643d25c50102ef2867458f05718080db0456370090a031366be3e24cd7024f6468993ee6c04fc1b86a4b756076e9c3b6b1a9063a1479743a2b946a9939121e50ef56ce13f1f01e8e421b1bf7050931cb6eacea1cf3994c7950daf83d5db47d8517f80384087e0ff82b0a36d2534e65b470eecddaf9631f60fd7bd49901587938fdfd2317d8899ecb14602fbf8728c1f1a7263f8dea75128af5ab21fda71daf4d6e954642452f75a74695ef4635364892473427e8876cf3399e7edc16de9e4b966616453d96a270b91bb791abb41f0b36dcc8ef28d09c63e4bb6e123e0ebf775d1da3e469ce11649ce6b01eca4ed62821cc9ba842cd11ed9a989a15fdb8761b1bcc16a71c531b858fe3c3fc4f5ecceacf657c166de85e442cae92844e70c5c7f680821b787e6b06c29ccc372ebdf8f21fd2e444b962045cf4c28ee79bdefc6a79b0ec93c0f9d1b26f0dd9a862e3218b3181192e5dd81619209f3441bf2a9a56dc889303ade16ad80b9bfe9afe9b470b05f52d086fb4199a12e5c5b9f93aae6624746c7aaac13294034d07cbf57b6b42077dd95674d67c9b229a6d517dc951fdb0425917a7099b93ae4479f4c45f63018a1d6bd8a4bd54c9ef3e097a66aabc0b1f301b38335f9191db35a107311916d66c41905c92b4cf8b9adf1938b31d589795978e92822cd90dd2ce0cce07fdc113666efbbf9eed3c720e4618a17bd75027377f215200b1fb8b7bce4977936b28789ca82e2d20f1736a51f1303ba53216f7f2d4e825acbfa2735c62b33712276f56983e0bbc2621abf489e976d38d769b1f8c560ebc815bd9001b63f9ccdb85d60ba0931e507ab9c4487aabd5dd6a6c940d7b796ec8bdf192bd6aee4a3e597fb55b1c1a9543c0a87d320bcae7a19165431f1aaf24555fab79ac92e5d01593f0274c1d3c395c6ea71772c0d140ec68ce23b795d18b3da25ff5183f1c59dac63589787dd11f3ccf48f8af72954df5cdbaf8fae1085da87443ff05259d38a0a0f127b4c7aceae280e4291313a9f1d4ee68e6919d222665f5bbca80a6fa5230a0302ac17c57ce684a920024908b2d23a019101e4dd3f5ce493469e96c50373bf7ee74bc94edad6875a0dec5fa4470b76421ec43000677b23c306de206949aed23d6b3bc57b6b4a52da50c7630d10093e9f0b623b08a473c714a1d88c2d10b7adb255b3322f2bbbbb442b66664576c77097444e905a6009f009e00396766c10ea6343b94524a29a5ccc241e905144913555957b5d8c54b47dc8af4a004982294004d0965427fe3c117b3f5b22a6a9222e87168c56e3a382c501850b11708930258221dc21e39f8791db769d9bec2300c7be4e0e775dca6653b5f39bcbe6def2d40f196acf7de7559a6691cec91839fd7719b96edd950e7812269a22aebaa16bb38ebc8fe0b32a2b3060c17362eaba22629821e8736534e681e8d8b2592a142c8ef7236d4d9b898ad9755519314418f439b0f8f0ea5e2c473f07b0e7ee0f771fe9c839fd7719b967de0d8608c71a40dc54def5cf7c85f03144913555957b5d8c539cad950e79920e1c3a383c32285b5d65adb3bd79d6b0f69a1a1e44873ce393ad4c9b477ae7be4fa3144d24455d6552d7671761e28e38bd97a5915354911f4484743690040e36289a0a853d75aebd45256adf792f5deb9ee93eb0e9999c5c9015be721d33946c6ffef2684d7bdd7bde775dd028c8c0f0794c96f10031304cb8831c6b2c68aa3fcad4c2a3089611836e5c464ef5cf7c81f84f3409134519575558b5d9ca39c0dc517b3f5b22a6a9222e87168333d9c8b183171a5063fafe3362d8bf7de2b35f8791db769598df54690cbb2efd3daf3346ddbb4d4e0e775dca66593df0aa8cc08893befbdb799cd9d9a8332f9fd409134519575558b5d9c634c1886e14b26e46ff19d97b0d35a6ba794b677aefbe4fa4750e7812269a22aebaa16bb3847391b0c17b3f5b22a6a9222e8716823e1e31b3824628d3566daf307ffbbe4e0e775dca665cc067febc85c96c886655916e6c126c4ffbfc4c860a000648670cffd2fc0c860f0214248c87ffffdf7417830220c3b0f3b77a04c7e8780e0de1562202d45f8ff2f1380649ffd7f9611288040c2bc442291302f895918869eb70583d4a882c14fd21c628e440289a19931d60112a060784006b108053108c32084104208111042081110012146400831c430ccd801166e30133385ebf9db761bdc109814cf2fd7f908581223802e54b3e37b8f474abfd8afa2a8662f53de28571e4320c7889f885cc307850a81572d4f6901a313e3fdf8910cbb62ee1a930a6c0df3de040196617ec30b185dedbb28416fab5c2c2e91ba563ef1de9660ab9584cf6ec1ff12fd1d3ee3ec4ae06d74aad92a653cf818429d2e3142e712e2465fd7bb778f6e76ceb607d2c7a4810f0a78041176cba074924cce20f72c272935ec33fbf8f9bc52e1f90b9baa7d0eddc20c3efbecd3103eba64c9f5eeaf427ebf683bfaa9766e9581231e710a380579bc635b2e8bf82f0ca786ac088d8bf573f2d95202973c2ac601dec723cbec9abf47793a0a71ea856d58f01a856b66e089764bfe1b6202c1893ad910bcaa4893bbf57794d0994bf66b948ddddf0d7338d59dfcb8eec9ea4232444f408c26b87270fd32407bb77e2270ef7cfe6a5eb96d343bbca2e42f8435d8af5e0f81532da4266dc03a378f4312ef5230ffd80a22dd6e34c8512710a8a7e9debef52fa0e71ff5184bf3ef1a70108e08a9b7008488a09883c26979202fe9f98c4a84836f75686e9217856b747ab5fedcc4cfffb4082e79a2e81de60f8edbf40a7b26ff434924842f513b0fbe1332600d2ac8bb3ad8d1999f748f9442875ef73df4abb959a846841716a2cd2bde711748edaabfef30719d54cbd548e9d0ab86aa4324d3e2b6b5a0a27d7aea8ac2cfbbeeb64ee723323f7dc0cc1323d214ee3732574f9b31a7fa56ea02ab7d94df185e3f36fece505a678ccbf56b92bdab4236876a316e231c6e9b4076e4f78bc659e9fdc6f98a47763d38f1f77a2b2b318ad2cc18e546c0bfb8cf78deb377f3533df1db3ac5d11bcacfeeb8ad9cbb6b89dc6b687d7a68f0d7cb1ce2b2293fbb302c874f403efbb7500074d584ba7b9320d3ffc643aaca37f54016a5802d61b693114069c87cf7266b0ad4bdb6cffee13f2fcbb4eda5d8aefffe4df4e8f383656716f5dc7fe901f62fd4a280344a1897e5627ca222dcd3fa04710efa32cd87723b8cd6a782d4b13f81657d7dc3a0748b861cd72e0aafd1b21341a2d4a783627c877febefff202d306ea27d6759058045fe7b0411c8ff3d9aba6c48b84eb9b38be1322aa26bb2fee38b20a0d37eae8d49fef49a477410122e6fb9ae9f02fa76ca51c20563cb21ee3b12e6d5a571cf1f3b3eafd8479080f69f0c0a002250d6feadaaaa2b87def7f0cc9b5bfc419da3feb31c8113107e96296bcd7f0cb49cf2a5b811f02ffbbdc8f32f38000da942a0a3827d1ca8b2f3e11a90f8334f211b27d8fb622920e03e0ef93ef5f75382ee6dede3b0efab7eef3698701a5bd86bbf0a65f3b2d4af5e9ffd1ed8d95038fc31b8d8bf70b1a3962a66e6b4383e3c388fed5891b3bfa386465463a213a3733c963c0f075164621b7611c022cf62e89e6865490c513499a3bc11f82f37bdc8f12f38001aa942a0a38a2fb7a594765e7ea2c2f0509adaec3c9a89f7551705cb6fc07f0bfadb862ff73a019a0cfb5aa64f83d8cfe04ee31700e39a7f8d1a105163589e37caa5d3b608d8e651beeb24d6f1837ed0105502a1c9d7e1af6e7b13b478fee5a85f8af28b69b37c6731fecd49166b9a1fe5f2377a0a8f010f00150fa37e9dae8a0eae4c350993bd1f3cd57ac19f1325b50cdb5de7b0ea149dc4330b3a4738e57154e5693485326993764a1ebff3673352c2bf4f201769df13011fd7f986f0bf0e05a0e143c109e769cba2b9fb36b7ffa1199d9c38d009edc3189d40631c269a8448c8acacb7afa08040e0fa54cff81cfa35994f7175f9b6c5927f4150a25f8265ffbe21404acdd4971ce0bee279a562d75ef5da42e37ae055a3f424994e43ef590cf602487fb1a4dd59cb1214c5afcd4aef744a4bba7c5e9e0347ea1bdf4efbea46fff8d24b5072599f2d8f78ef4cb88d85d8a70bccaae42e277a7d8950e0ae5d43d790df80915c85088051889954b24b349ce5057e5205631053205e15271df95c32d36724ffc26847aece08654a393b89bb06fdc617d13772c92f2c8cd9c6d8f7c2580185d2124ba8f298a2aa11030bd1edb4bc720350dc34f29b19e30dd1b3b6355b6b092184ecbdf7de7bef4a104b101310700b2ff4b056f6e1a9d1ed4566babd589db955ed6e2fb6493cd96797e4e9799cf5229eec85696b7f61624a72b209bc45620a14135356e74a115376279eecad6d4918b72d7b1b7b40840bc40fe3132b6d13f049f693cff7d2e55993b349b6c0a56c04e571f275e630ddf4fa6ec4d22b574ac2b24c5838efb67d58c6c82bb94884198255c9307277b5a398b289c7f6f74d72570c38e59ddca6dc6e2f29d7e2c9de788a47d817390223c6651a70e9272f71727b3979f2a53ff99367279c6dc5937d0a6799c493fdcc02979ef252e9f27d723fe4dfb399839ba6397f52fae44a4779a7704650ecc9ed51382da2ec6b6b6f75e48d912d4e3cd9c3c896e505dc61b7d6da7f3ef23e97987ab7d79e8d4acaa1df67e3b61de5ae5482a1d01f77a1a0dd5d2820c8b6eceb35aec863b5da3ee330cec4e3e2ba78e5af4c3f20b421115edc0618c8061e169c6f4224720d30720b144cd172494b09257c1b88a94e25c21bda5868f9c9059c1643cbfb5ae4e31f6e20843910c22251c2fc02219c8134374d851530bc9442422b620a0a286bf0fb7df4033384792d3837371bb83d804fb879100b2d2116132b72247738c33b3978630669861b12257f2f2e958ac4937cc243c9638183057913338c8130373063b8248f780a9190200bdec4d37b076fdee18dbc8930a119640f07d64e9f62e380df6b51d2bd85f37ba58e3360dac7936cc26b6dd5daca968829aa55ec955e7bfd753040bbcd46ae6bcfe8c6433bfd516f9fd5df5b8efed68b00f695956a0cd0819a3a96a07f174f37501f0f13b5154ff2b4c8917a3b9b57a778c47ce5ce04fcde9dd66397acb29668d6059b142879f5d1d7f314988731708aa8824b643010536f8b22323d7bd2575fcbbc04de7d6ee8599b906698373f6927ae735e32c18f6552095a81fda3ef3663ae44c2fd7229bfbfbf975f6403be3d60e92eabe5290ef04a0bc330ce09523f26dd035fbf2b17b6a5d7f588c1869d9530ccdaed372286728b6116c3300cbbae631786b2b2f26c09d528dd5e504618117d8583fde4c905cbb60b7c7dc51eff3dfb68d50db87b70c05d958181fadb5e50cf5afb066cdd80b3c3db1d1dd844a78b36b05c25fa0d219e45cb066c7192b02711d1260ef42d09fc70e6d0a463f4c3220d306812e92a5c47a455e2ca4a36f1b8bef21cd757564ea4ed49294721d21648ec946c015804e9f124aef4eb994e8f6eb7175276e51cd9af7c9d4843fbd151568834e45ea3640bc02246f123aef48c03715df4020700b6db2496659308b106dcc9204ebf0ad745d12aa4d817de705c39fbca48e519f75048f6a7df88904422cd5099f115aebb0e02226db3078c30a2e103609358ed5d9d1029dad2edc5da83549ea242e35538d852e7f610bfd0741a87b90bfd5e47392429617f2931faca6f67a3bc921f7cb67214ae1b7dc6490db8be92455be0ebd935f88b4341b9fdc57551f475b82901b38974f81513e9a35b52def1e269e52f9e461fe52e8a281afe1a3d860ed8267b942cda025b786d25ff309d947f806e0f445e79c6d38ccf8dc76907280f914bb7b9a39167280391714b22e52a2a5c37a455ce59a8921d5ecf300da492a2f2928a8acd1388ec983b22ad92e34bdb8b8cab70f1972bfd6d4a44a91353315f87b9f44c85933ab2a5f2cb44c6e93ae4647cc47551f4e819b7bdc8b849899443140eaa48b98ba253b2117c1c4fa60bf68b26199ff12bff90f1151979a5e519f792b8fa92c1c1cc7e66b9ebe267dc1e5b9497aeaf1ca2e42e661c89eb3ed0a477404c1f8808f8dcf4f7c92fa246b9cb3ee35d908832e58ef41931c51e6611c0be8e0264db11fb921b8fd3bf0261b7f26b743be2765cf67005e52fe33ad28958f940977237e3a40c44f6ca8c15d83264fc8694c19d88e0ba0df48cb770dded198fc17551f48c99210ec0dff61280dcd340629f7e236adc6cbaedb8320d73c780fec1f2ec27ae837d650f18d1195251eaf00e4845af74d7591e85116dff22ca662c87dc0cd91d6c0f18d12bb96340df884674108f40640771b9bd04f1ecd22e4e36dc5eac6d82e101c075363b11bd6821bee51b3aa52038d824a2e4df8a8525431d35b088d05bcb968e34e094d79a2a68d080ad0eee9c6069781887f1aed20cf1ec6d28b9a340a31c76114ff2caa44e96337b067cffb61d3f56bef2ec2d17d866b9239bd85b33e0d1ed8c9dc2ca940177d2ce7456c6ca5826f8cab5067b3ce98b789264c0f659b632b01bfd7af6f0e82aa3d1caaf959bde5dcf66567e29b1f21fd74c4c5d2552be9e3d2b7176c6ca4c6165ac7dd675da9c6b4dae3df164e22a4fa589a708e0ceca8066a88829a823a3bd8c952bb3acb9bd58a8c343a30b2bf32159d21fb6d6e68ca16366227a9123f6da31e0ceb25e5256ae2c7725d01571451e0bc6513827587a8820b8d7b6853b8859999978843ceeac8c9d89a977c95615c200756e97c414296257e9804bff183d7b0905e6eeb664c828e1286979191cc82e51e94aa9d7ad62ed755d17d7019795ec6df06fde8601779605f3e8ba48871356d26c387bc4cdb661c0a45c676070b50a2b5a1e556beca5b960c0f0a4e3df1a1b68f383a79136aa7568f95a07a892371225532f9ef640ad85f6e5b4cd3fe041cf208c0f27da1a2e34ba9ff08acaededb52c5ba7dcdd21728769e4aee4f21aa752ee6a803ef116243f1ac6752fa74bdcd518d7a4e58b271cb0b10cba582fa769bc73e2e54896bcb15fc0d93b792391c8d6121c5a51c1a9f1582e2e0da185166aa51d3322143bae0c9bb60864ab6413e456ea697050cc580fb22c3ba3c4d6306989c27a39ab23735e9a5bb3e5207dcb258e76666564ac8ca5d1e1ae765bb075694a2a33647b0177b2350364bb807f68c064fa0c3414e93bbb9312c813f6bd9695afe42e0428b71fd52a682a0f69c62f07c5947114ee09db3280c83659560e26bdb3ac2de0d0ef472faf61001517234a27224867c125150d936e36fa758d0eb9194fd806a17019dd5e66ccd87280402650963a2b9c64124f2d2de00eea846c887bdd24aade0a736f85fb5e9cdc792df2234e36910f71323432c809626fb31232bb94f1b7adfc46b49f1089d16df6ebbaae6b941d5e1767afcbdaebf6a0edc5de9017673fe26e446bbf6d2f365be168e40e368d679c8cfb2943c6e34e4cddcbf8677b91912196339d414d0677573848359477373d0991e8a0dc94c8da66a8238738c8743acaca8eac2b2c22bb8c54599644497b799a913b3c44eeae4e4cd1b8bc9759c0f7349e3d2c5bf12499c4935cf9c5c1860d2fc29f0f87b9951c23cb922aa83323671928f9ca9675411d7965692d8ed1edafccddd3e05e876243ce1ede7e242f779e8d785f2112afefaf9db64a30cb2dcb215797bcb6628a2577b0590eca4cd97b2a2bc352735896c4933c8b95413d888372770110e35796616998dd345a390ed8a31fd75166c8380ed828960bbcf2d12fce03b24d3cb25fcfb20864affcb529ab5e842e83a3f1191ce8236e88af70a75f4ecb421cca6970320ee2667c086ef413b7728dbb201a0f5d7a11539dbc01d1c83862d300ddc4c596ad98823a31857b26cc9372874608746990bced89171ac7013b34c4e3f6c4cbe938600ff18c6a260ef6d5448c2000cfe0abf1d3f21bd1c4bd262200b933410b71f9166ebe162288e882b41042e47b05fee974ca406a9f86b8dc5e8ce067705362886b8fdb8b76fa10a72c994494fccb1059b6ba6ba3c5211a075fcb498867939a4e87af88d367901e62876c219ed1cc9eac10b726d385c81d911ee2f226eebd96d3e7f632c46970261ea66ba77120b24d87db0ed3b52c02d9343290daa0d033bbbd80683c6e2f3472077ae819dc9e7820d04f3f401f02f453be3698c6dfa604e843e47b85880b0cfaebd0638020e83b40a68b40662653280e0971f0b50cf10c9a1e371d1306a64d190ad075f88ab83e83b4e97288675133712288d726a63a6aba1c02140ae527649f72077b88d76263cab566e36a15b1d2c4933c92559aecf2e22acf1698a7e5c9e5fd9ce4f750a82c0a2277da7d2800e4878a913b95869c64e160b364cfa94bde8abd6cebda5e2ccc7ba3b7f2583a0a7476d9d2481d2157fa88eba4dc81c175592e3d2b6998832b969782c78878b00b13f77a06371b84f28863a1bcbd02ce19d7b974b644dbbf7b63e9160b9cfdfa0a37bae59c70e9d1e810623c6249d55ca1cc56815c869225841042948fb83a53659ac493d4d102a3bc833ab0095481b96ba2b38f1eb71cdcca250a071beac0265a5f7f91d4974a5f570bcab46cd99bb2cd5d137dbd78b2f0d7eb9511c438138cbf8ef114cea4fdf56631d9924c489cd491ad1ef89f1ce4c7f87874963a453cc92c0bc2f22056aec86c6657ee4d3cc94b73ab88a79a6b03803f21feb617217e6b32bb6273244a92526e2f8dc9ce2149870ead00f3adb13276269e3e177d8e90b2a5220775d447b92ba150394e305f108e55125329ef4aad627a875bc5f421b86e7669e590b376a7af675c4764a6339dee2cabede8a432343cca175cb2d0d8adf003343ca2614b100f65595255ef9f1c71b223ec4a23237c727e48231cb34979be96d92b5c47a4570ee50a9772cb817e711d75e2ed74cab3cb9a5e8d885e3723315f89724a4a369968fc6d49941eba2c7100380ad7d5682c0fc175b843dca581e264006093e0d1018003079936dd66a6431177f2d1e588b3389635b2497c703fc9a61ea29ffc4474fb956ef2c0b487574eb71721aa807f6860f4f7ebd101902d2b9ea4ca887b2deaae739cc9c78990cf4ffe381e30485b20d17ec4bdb8f1c0241770072107245a16bcdb0b8ae9f5c559964d327ac6d924c789a991bd656587b367430eb665a170b3311e4534fc055f2e8cf3804b430bd3d82dd7b134d6a92c51224243e2c12c6d88ccd569ec426cbac8a4b1675c97e500690b6f48cb39a135e4b2436ee56fbb48dbcb4a861848bc36f12401c0cd168294ef0df6e144bf3595a6d2549a4a53692a8d44799671b7e6d26481b357114fb256114ff295e65e8c4b25161618fa38b988e55910cfa01644ae332c5c95a9362db167b7dc0f2c77d004330ed8a578b2ac1269b4e2840b76d993b891fc95bf55dc9a17940c310a378d7c0eb78fb576f4fac375c0a561fe71dd1e5bc956b2cb75c0a5b1fc037229cfde966599e53a977b71e956c65a4b051c2fe333de59992659d38bef246ec4c1ed65c5c4756fec2a1c0ad7e1c632abcbb2132e6d7d9cfcb322d3d86f44c85dcf565c1acb570a77c9d429ea4c4cd94b1da9129dee501e202a4c8d699922e20247987e407032274a9c285951de4ce1ae26f73acb20966b3df75619867d25833083a36c0433087abdc2e99018974efd80632c82460f37d20b38f40cd19dd4e9d9618014be60e2e4a61ea27ffec9413e17e5e72177091742b0591d99c727b222b29ac149199c8c813a2f9ea0cb758cb3cfb2aab934f6ecc19b9e0366961369f80793680bf8441a6e309b76ac3c7b8e956727d277837f9bcabff2ee28b97bac86a387f227574e44480177b2d59df2e84fa264d2330efb85bd849d7046b8b8ec40526ec1255c3e2e90f5c9a61e9f8b2efa4022abf787eb9f0cc3308c6118cea61ef8a28b30063a86309475dc30408dae86dc819b680b2cd9823a7007ea409dc7922a898696920e2d0f593a3c1066b3b3a0c2152d3f63e614510500d6c3e969d292d59dd4e9a13870e8e96ec248d1728541564c7550a7ab3c3931d5551a2b1353492a4d4ce978e589a979257649cb69592d2513a823a5d48947c8ebc8564baaa0ed58545a44c1c99a44ee104864661954421b70e80053f3850a1164a2382e3d1b32d41dcb2908000c81a2771802623101a77f35e4ebeeadb9c3b88405172864c11db873d16011bf01c4d3f4ee607bf36ca434fd4572739a5e2c34bd5834bdaf2ca9aaf9de4854ad91aa4a849b2b744d02ab69959128ba448d91281a83caaa3194feb601cb57987b2310204422c294a01095d0f40fc622348d96467626353983e706a7e4de6be9ae0e3cdcee4d3c5d3660a98a3f78287a22dc24343d7d42a4792d9482782a1c3098b6d9bb76b876c0b09f7cefd92bb2f022ceb3616afba8e4d99030b8367892074f0aa12455d0873b9c242a0ea535e032c42fb4fdcd03aebf78c0568744d9c76b077cdfb3bf76c03177af8bb68739e82d13f164df291dd4a93d77c05dac8935f75afb5b071c0fe114f7d24127e2d8df8ba5b54fca2867f050f6d6bebbd65a99d7622d4edb6330570e9794f78aff8e5fd7f16cc07be1104a5f172e710f755dbbbaf7f5beaeebbaae3f966b06d963e926abb1279ffdf5025f7ffc19805dc7773c1bd7624f62d8c59fcc3d14760ccb58fe6bc1debd31ec8f05cb3f260b4609a3d333bef866300cbd76c0b361ec9190464c3b94fd7cc6c195e55e43163c958491816de2b5ac208c545de0be833878d97b26cfeb89dc173d8f5d7f1867ea9161cfea89ac8c643a326e89b79231b09ff75e6bed69dc038c3470019428e8f918634fcbf77c21617a80bbd8137b606e1d30ec533ccd22f1347fe980bbd8137ba4eac69eab43461e4f0d7d82896709c2f4f47ceca93a346a7318c1687bc017245d31c0f4570fb87bcb49397acca469864252297fc1006339684b118f1752c47a36e0e52f0e645e8bcc322aee1430cd198db4a225a2fb7aafcc66b88ca6cb66e869628a4a8aafd3671797d164331915d90c7c46454c4d7b219c912ab87af066d14e8e48279ebcf8f4e87c6a60620a1e7e7ab21919453c338b7ae229a2007722253c2d676662aafbf4d0c45446c5a747e445cb775a8fa4221e9e988a2d65846122a148494cf57c7a7036e3806bf5e9b1389f1e8b834730366655886cee1eb00987dd60b62c29f095f2bdbb079c3de05a659f9d7b45364d38d6d985651731258fa914ba2b3d0af38c2d796212647ac6d6b3a1d2a4215dd24b624aeac423e02927af1760f82cda02cb4cc60cd963e9321ca9b597dec006193d7c8fc6f71e332b5a3e837fef740afc9cb0398fcb6ae2c9427bf78065d39cd5d0d71aa9b23816c7d6b4c49903ee6c2bcecbdcdd996d2b939505401061890a8e243a1b7e81464edf8ce6c33323c4f3d9943d703e3a64b267ce789a770fd84e8971b0a71ca20b7027cac93d40c4c8014b9ec983bb4ce66a770fb86a40cc3c1b2a7ddf01c12a3da16f123a207ed037c6199eeab601cfa16f8c3cf4bdb503be7ec5684955ca0ecc194d5fdcd5b429073ce570b5600f781a79570cee5276527652bab8315a0f75ff52f4f0b6f5e06d0c323c55eec93d6ae87b98c948553dfd9c912a6b97d896d5792c510e88a6b3ab05962b49d4bddc8ce018dc0111d317887b20a4b83a4d3fb219ddc4e07936b6a68fe1458c9e1398989201e8074d6d77293baa949d87a207d13c1ba3a6a74f81c3530131f3522976e8fb8b0518089878bacf3d40ccd83d6019acbe8ae04e94936f9e0d1c502e8b792dd70a724fdf0331933263ba4bd911e5f4bddd1c105732582ac01d08e62a82e93f3cf1444130229c67e3f5fd8747aa32997b9fd265343c3219a94ad991a87b2ca7ecc4d37d96b293022c83e7ce791f9f0c9e2a79ae950c1e89baef64f0f44dd9e97bfdc6685d39464ba26e17a3d5178899bea79113e2c91e4bc7a2d32b351d27d3f3b27a7ea5e6d950e9952b5690f4b4d7dd03aec7309b9eafb5d6952b9a5bb1229e566e566ae229b64ee3a08df1c8015f28c0352b3252056307c64ea3b0601d3084584a69e17b0f464b93add4c414edf9152b9af4fc4a6ba549544115f0ac5c11530f8b1c2ce9b92293a4e78a0d4ecf959c9e5386758798ee5698f45cb9e9f90cab2b55c454076347866626a6ba952a6862aa43599922a6a0137a36a1bb152a5a3c66c3e0c1b6d0d5e63496d335c3d8b97fc0b0b1773060749161f0c4134eb782849e7ec00f0b1bf47407a3a7e76f1f60ecf43c0c1d4b239ac1765e4bf7c9c1bcc07a7a1ee3f9a2a7e553726ab534282c289a11cdf46ccdec3d1bf1ee015f0fb856f4acee6ea3b07a9e722b351235f5c0f35a3e37cf06fcfcc501eeaecc792df3b7bbbd39e05ad18cf148d4ecc1dd4a4dcf77184fcf6ea58645476e2cecbad87561f10d3ad7c574c4543c03a27d3146895ae249d46345d16309263e10db6084024d605601f35a267a2c01692c109eacd17fa7f8fb669038e7949583ab292b07576fbb818ad53788227def128414b446772c2d7b5f1059c4f050576678b200e39c652c51f77de3e9feba008b7a624afbbda875f1bd2dc0da63aa7b2c4c62ea5e4523552a988bb18aa62fc845052355d96f3c95a4cc1d0b16a9b454c1f4d5b4acbd88cae40d304bebd9d84a7ac0746071435f1634f47d10317d8390e91bc44cdf2068fafec660fcec5a66696581498771884fba0f4c7a7621a6ed389bb4e3bf958fec30b21052366df9ab9344dd67d9a4659303ecf17dd8e32c44081692dd882cc0a9fb544f4cc5df7b7128a75a7deff15d418dbe2607d867ef619f655007a4f647d47a2d987ef722181560f94ed412b5a42aaeeedf9604c6d292a8fbab028c7d0878f61b0296fd34b9edb8fd7936b50fd7a1f4a78bd19fc720fde944fd7927e4c3755b7f3e37256a7743faf3ec6a1faeb3fd39dd94b0dd11d1ea10b0fd70b9b3ab65dbf60f07446f1c0edb9f6717d4e267fb87e37ae3ba12f4e71906df753f3f3633b4e4aefe703fb6d3db2d097abbf198df6eb71df3f41af7ae1003564b4ec6108630045c77cc967cdcaecce3bacc3ffe5a833b3a348e01389888493cdd563c5d2a885a3b36dab1c32d87bc698978ba7fdd239e6ef772762e2aa0a0b5dcb1f05c6769dd2c632cadbe6f4903b9ea75dd882a961c12ebc8055718438f1552585163aa2fbd38f1c30de15fccdd756f6b0d02e55cb8a887ac4e4a6bad9fcfeaa4b59e565a6ba593d506397f1b9aaef7676392788a9115718a6023315fd9f7dbefded840564c1251f1564606145e016de08d9cd006dec809ab88a718e34d01ee644e8cd18bc8ea98d2e19a610dbcdd01d6017e8f54523fd41e5420e077f8140b030c9f625780df1f8c2bd0e018810a23a4c02827adf65e58a66d1f8b8292cd11ba7b4c1b64b21c2cddcb8cb09884458ed034e07bfb0ee3c0f7f270b3f9ca1b9c02b2c0f799dc78dc18b71c6f66f65ed715105557ca92220aded02171f50236ed88ddd5fa5e4ad9c2f2b5b3889f0dac610bb0ec0ec3186394d37e3a22ef922463c6252638e74ada926909218490e6d9882d218d9cf134c57d2df259f501ce2094fd5ecbf60d48151c0244c9cf7797d67725fbeef7dde91a02c47ee52e95fde62e00dd419adbdc09d11da429c129e026c023681722cb01e82ed66019eaa4ba8b3551868a481367e46b52cf430744e25e7e01cfc6bcfcc5c12a5e8b14c2530044e266f8835784bc14ba06135c8eb43ccd3008af45be83b106d2d4b44c3f20acb44ec8b6a88a1d6689a8ed91dba098f58a37a8c063e2d9d07a3b059e8dd7bd3bf4f6e2f0b6674fb12fc0f5db291053f6db9b88a9fbed1888a9eb38aa42dbab1070f75a1b90db9b902af9ed703b135215bfe5ed7d7277b3c9023c3f3a3ce8f33e409fa0fbc01f6521f1f859d4de653f1278a80d07d69fccc46bd94eb3c0f3306e7280fcbc0ff999851ce9811f2f04f420477a8c4e7a90233d441f3dc893f7110f230bc18fd9f4c946e24939c8280711652c519d11bd75357afbe4ce00bd65df4ee08086fb0ef7762805edb9edc80e63e2693bd53edcb6551fe0cfab0fb0f6a21dc4bd15c61c13dbe1f60f9735dcb47f38d94c6cbf176bb9c3a5d27f3ac9cea597782ddb676b229eb67f3213f1b46d7f2c5bfe71652c91282f16d07e31f552114a0ac5145e14a14811724e44210cfa6cdabdb04cdb3e201c126ddae80221ab871f68fc824c0ec8ecc98078a233eb8827ba443c82bec891eca200bf732cf1440fdf7b0fe6533cb101bf78baae77988d6c7f9925aab6d37fe3181051f4d9d42e5573a5e39e006b19ce64280383a1a5cfb0a7bd3cfb07dc3d9c4b14fdfd12cc44a3f4d60faf0ba9daf150f4945234504a690bbd1470966dee1e774d51baa7cfdedde3cb95deefbdfd8d58d24ee9a5975eed251c4f94de077ebf26fa5d7bfa129df6d252fb329c89270a65e2893e0258a6e9cf1253ddc3a14f0131054f99b83ade65e2511deff459cae39d26f30194b60ff00b0c2fdfbb22a7a526b3894d2e661a7617711e16b8906949262d3fa78e431873a292b8242a89380f47478ca989f3fc94dbcb2c7264ea88a99c7884bcedc13bcf861b5eea27899229205e172d714e599d3b9e0e1823517305715322cb9986e5e0cc3060f872b536dccaca4e3bcba4970e2769f92ce2c41c17e04ea539a8c3e4bd071f7c70de7a6a0054dd1c712410b18be8867792c7c1b1f781a1e218dd3d1e9a9f44c9e8eef1cc1c674d52712a2be27495d5b2e64489c9a0c234bdfae500df7eb6dfb3a9d51ce0da2f079876cd019efd728065bf6756dbe2a6616f61a382ab2e52d1f4d66e2f7526fe037cc038c01de4814d634a8a3745d3fa5a7fed1eb0cd69ab07db83a988343155454c41981763a4ca9ee60177b02fed5d0ff2403a3c14fdeb2b439ed7426fb6f91245eada992c1e30fc63d24fa76bb677c0f0a6db63c01da9e991bc167aeb058e875b8ed8b1e6b550e8453c51d8134ff435439e78a2f4b3088ea797db8e7928453cd120f144b380bb520e70cd0186107e6a26c514ac3055090fd3095bddddeb21015f11f011becb5a9339c0420a6208d0ef027848ccbfff0f0b2998e9878514186913cd38403d6a1b315c5a8ae8770c919879cb91d26743e201a6e9b32b55310673e0816ff5a4cba984af54997ad8cfcf1c24c6600e3c2b7b222b79c9e098a6ef6e4fd30b265aeeca8f91f91a12451f391c275d239ea88b44d901bfd57c772df756f746aa668d44d1d35973d3b49bd9e4ae8d44d1431ca86449d3df9eab4854c1c8b94b62ea6da105244d9b34bd3977a729e451e282377477799a4a96169a7477bf68fa0e379491ce9aa6a7d70632e18aeeb4ee5c96d0dd4b72235570453f5917e6d9787d6da4aa665a1155134944d1d3bf9b789a03ee2ece4dcb5f9c94facea5e9bb1ae7d9b84e6eb868c062683a59313eb29a3e8397499a4e24f144e3f6a2dd542f6e9a76cc17279ea81c70776f709afedec454772f92a88230f7464aafc594c43031664cc8e015f01de59ce5de7b6dac96564b2fadb4464c752e47a40a3e9e860727e8aef492cc15642f85b30f6771e4805f63cc050dff7056803351d03066b6a0e184b9efe6091ae2c34b39bc01a6a4cea51b9e0dd073fcd0c9161e72f6d0f02f77b2a7a1d4434ab6641d1a5ed2a1e16cfcc7bdc61a3e4a9c88b9d71227e6c8d63c8427fa882373ba89313e7eef61fccf07a73f9ff75e2635d07b9fcf677b1f0c5fcbfb87db380dbb4a95ebb04ed42936e70c99099ea573d1ee1f0e1fc6418414c24b3760f9784a4f986228e97cacf4f5199d4fb4050c845e04b04fe5936ac016c638648fa5c30f3ed804bf1f0008ec1dd972815f1389f001d96309413c96354e350c105350ccc624966b8f05b180851cd6a4920855f424c2929e518ca49c745ece4925adcf2ad7d1dccdfc43d6eee86dacf3efd9c820162f79a7a5b5523bafbc220633ed3d1b4fab5964f159e472bc8602c2792d9ede9f00024320ff849d8f5c6c221286005e36c1f048402cd8a8e0dec6dc6941507e9fa17001b3ce80d1c20b9b9644b49c2e2d2b8da09697d0082dff8080e30fe1d018cedc6116acb397c295aec02c914fa5218db26596f026299f166fc86978170344950a4b2bc1534323669c31101e4922c67808bdd02fb2641083ee2e94f36e816196ef2933618d03075791ebdef5074ee8b1590db13488591d89eff09337d8de7d364e6cc89634889613b2648c47b2ea527f23666ac09918e02083181c9d21a09cd5bc6fb6e2a95ec24d83560a4e3043cf2ac8900a0718d9c54c1a64d70cbb58be996b3d54fdfb3cc39b736883cd93499cf94554379bcc2ebada5ba8e40b44d8590519627370569f0719327710b33a02b9c723ea2d57424329e2c87b2f7a44575b5d4fb9d9d2c1b535a906b700c20c58ab2043ac0b685647e287cc22b45647e03b5cba676849296f30cb504fba7e3279366ad7dc95ee1087aedd5d43d74a8b288199eec575d74d373f719f23f6cd4fc03ff43503becf3fbaebf2960177b3b543473cd59b5e93e2a93efe01e39d6ccbd967f69a69396e3bb0ecf0afe1a6049689805c541251f519a6c5a993655adcb01ca9cdce6cd52ab99743fe144ff527a9b2af8f5b4095cd4bbc54bab976a1ebe1f6c2443cd53a73e2a9bed689335b38b3a5c9c48843f658b2576b34dd36faf872945c01b31a42a920b3baa02329c12b9ad25ae12f13ac238a78043de43e104fb046aa7e088f3cd583d08a670336a56568fa85a614f2504aa9023094271779985de289425516127146c413bd01620a26819d5ea35dc0b4bb6f2f38bb5ae9e4f213196a28fedce6e1f639e43a23401c6cac72af2167046cf8e96ae55ec36f104228e107420821d660e64ef144eb9643fef144ff054055963ff05209532d77f775218a78a2548c01439a0c67ae18b08e1503220a427871a9a6a675681d3541a7a5fc93327b52157aab1067ea711f7a28079161062cc0d40f914b7456f786a48e189a72e1349be634953514a31c704228446d4c4c61a7736218169b6214424843c7b84c4487fe5e4359c794428754c17c6182c01e2eb4c0661564c81d026b75447b9021710637abfb9a234f7565cdb371d2f4d20a4ae51a9aca3234bdfc42d32c94ac80a52099d0f4b765454cd9e0e053d0673be66a0cf00d0384c9dd2df5050386dcfd02ce1e9e54c413a58947d0e3d0cfd03cc10b2ea8a254c254c6c413959152c4139559ca2cc19d8ca1b162b6da5c956e50b294881d2f310c6162e211f4d70ba74b4f54d6c423a84d3c821ecb55d6c4139556c413b5e901969735d28662aff5d8956fae94dec81a4a29a5945ed6d4603af7440acc26cee0f897610d73bdb53648880c35a85905197272b33a727d483cc1ceca5a23d80de89c7f9dfc41cf9f4ee88c3d32f740180ef4b0a027f6b72da143a2e6121235a59494f6e1a96efce2d9803d6d7061f0a40a7a7601c3863d7183a7197be21113261e31afb85da7dcc5cdae8986d9440f81d0366273cc33848145226a9edac818d803a1c692696ae36d7aefe502d7c7fcb4a9695914808e1660b46cce7a23588ef9ea925f4414ad875db3ecb1c1dded29d59b2fad2e2c2a5970470358d913539df40226a6ba2945d353f9454c79318b34fd932f4e994864ca5b832c7bda8da96dcbf2dbb8bb7d6eb5d67aaf5f138eeb9d81aa169f63b71c694a4a298d5b035e4b9b23de9a70c477e53eb983fdf9ac9f12873feff0e737e2bc1daef4af35184d37c9c75793c49395832ce2f8225c92bdd423c431c64853c50b8c5bc842f893c9ec524a29e537901485b0e30f8661b9232241b023121b52d28da9d0470fbdbb9df2141847b909f467204ed31e23f451e892c776ed206e7bc6754d74964dd8e5f1a709fbe71a280365a00c94bb26da84659cbb26ba89d67eec929bf26a929ba0dc3df116414a8380486307fd26d025a86380e8dbe9a6233b288bb6c0d927dc1a001bc46d7f5b03608b7e236e59b405d632102a3a28ff107dcb3f625cbbe43a519ef194423bc6df4d72e30177c4c82f9e52601c254f20126e498c1efadb9290a15128f48c6a320b69a3aa854259ee482119caa593425ce9ca3ee549593e5ef0ca44327eae65d025776fa9743833d858aa4eb4bff7d1e7a2dcdd50fe1ce7aef4f909f71eeaf34f967f5cc7ae8d0371efca2eec93415cf7067d76337a5e1ecbdccd902163654545c5644a49414129954e4e62c4800183441a8d44a250086310e8f3d9364dcb320cbb7a5e2d45a23cdf59188ff1f76ce07774142377b5e74987c1bdd742ca5d6df9906d397aaf2584b914feccddf6f77792b903fdbd89de0ee23e9c08606759fea11d7bdc78c063d7f1344dd3362de3b05f9cc6fd98975cd7446f015f76975dfbf67b8dfb813df68deedeb70c8436f6a7f57511a1e99ae8b7aa95c3213fdf130980301ac2902856783a193da458c03b5e090d580cdde3423de5e0dfa603fe46849750c08e27a9820f151faa115f4bfc9928e9a0c34b5dac92638529d041e55d2537f1f9de6d2ebdabc4d37c3c95e269febd475fd5f1ba9753e3d154d1ddbd306d1b91de65f21e5155e4480868ff181dc653f081506af4894ffa8ccf2f1153a2cf271290c5d14fb89191d06f4418dce833b810d0fe81633ccb5eee224c3f4b697ec236c5b7db6b4815e8f35926b5b7e588f1936730b8ee2de330fe9e6ae51d6e18a5867119dc0aa7c265d674cad9bf5cdf01a117de72f0af7b9ffcbd5a4bd3a6e493a3e49397720906877fc2e1185cf78e9f490d0687ffb69781d0a659c7886300b704d723a266be114ff38e017ff2966f13dcd59855bb21b50e08edf7eb86016a2cc11507c3dfffd147293c054221a638e0eb63ccf0b3860190f4fc068044d5b3438e0262ea59818b2a7a967ad4dd63c970b1857e5df47cb5fb634a25a666cf4f964e0206b32216cc3a6fa4aff431caf8096313b46041ce9f15b280847e5ab040a74d32e3e86e3f0d6fa02d2e9e189f8cf311494cc98e588858f454dd1c6f246a7ed6494f3d5135aed0734e2c51f34ad4a43575a6d64a698c371d6f78669c4690695a6badf5f7de0ab7c0ef19c6bd150c8c8d44a10dae28365f45a10d672fbbf7e61ff5175c91f0952ad29fe81b46ca97e250a9b45decbdacd6eda52271dd2b67708dbf6bc077cad37bffb9afbf213f9f4ff6d7252c5542b60731f5101dbb28ab80c8eaf417e5a9a2181e8a9e46961b9abee3babb2ff25cd7e7f2061b1764c81446e8596daff5b6e82f131a2404b31067f2118a3912451fcad146a268c491287a5bb4e7b67aaa4ed3d7d6bdf7de0bc207cd34e8767b01e1dbed05678867dfd72d09d8a0dcc1aead78a2b64653ed35626ac321447f2a16051b6460563d5d392e1ebbd98979051ee156d3564c513f74cd100763997e40405ab71b2ca7e1e7747141a9e6bc912868ea8171261fd8b3671967d64814644914bc8c017c8a44018671ce0855330622116168526626d673ce39678c54d51d898287a519d310d69d8b678db90789fb6c725cece9453cf5c4d4cc7247a2ae3c7b20eec91353f3f0d38ba8a2c10ad63cd46b05bc80268a5aee48d5a4c343c1433d343c4143da82863caf051eee34cc584e8d58163c2d33b8418c5a3983b3df9056d36cfe91fd5a1b376bb32ccbb2dbd7967b6bc0dded77af0d32a4083439abcfb3ec9af6184d3db04bbb9cc19dd53a007bfa87f6d7423e0f62ea113af650560191153ef67af36ca0b47c451211107a5797b4ac4a5ae25bc2a397262b346f26ab63240a73261f78cec81e89925346d29a18e0aede488902dc45980de445771387100dca6f484c6724a0420f6822f77a83f9610f7b3ae33ad89371f5d8843d4dbf5084a6f40adcd59b7ab3f1d88a19a1b4a674fd55f26cbc96b35e2e74fdf59a23559f7c7124aabece2a7307bae9fa8487aaaf3861e88a454e571a89aa3312556b4e9db96dc05726a6e4e79c534aa904a87a11a6b445165dff60d5a915c2ed05ff8a78aad126de6097e7e6b4a46af47a75bad69cd792d59c988262c625bc96fa988457447d7d5d1255b5d324cd028f2ee473d285803e7a7c7d86e7e8a00b21fd7321a3831e49ffdcc7e873d27d7c4ef201fa8854eb57a3d0af5f738642a28be4bc2e6a419fdaaa3527c4bdbe423bec4d3cb6871eeaa93dbb343983e9af7c73e2a91e7320eeb624aafec33d7871e680b37c239eeab15c239eeaaf7a58eb6dd58b53eb55124fb524ef7d17271e5173e211b507f417e7d65f9eae97dbb5dcbd6cc0f3f1d2e6b5d47a0c73274826cb629c910ad963e928cc839faced932555530c0f353f5b13a7f116a617f134b1be308410f26c1cd64d6c00345baf6566ad98826223c06b9917c02b625e6584cb965dae7f2ee41e7421d73fef3013b3f56c60169bd785807eaf7718f47b1fa0dfeb1e741ff720d005d29e3ddb7247a4b7ce0922485a9b0de10ff8bae5d872c6691cec261a762cb089789a14d88044cd9a67cfe489a73be79c7f2e8fc2cc9b45367f75177930676442cfc332bcf86ca4f43c64f26cc4d29c77ce3bf48c43cf35f4fc9b3388b5353105058455782df3108b57c4fc8449226a9e8575135205897033879ef58f493c4d03dc8847cc5f1efa36d8ba17c79a1d0ce70cebb5ccd32cf076fcaec44a02bf2cf4404527a05f163d6368b8c1679f832e047fbb90cfa703f0b7fbf81c6472c0767c1fdb710e72a48744f900fd9383602b9ce1219c91a80973c9009d1144945430a959a2aa8644cd98b23230865e01d7773086c78caeaf1c84314c226a7eaacc095bb254bad78b77ce095b73c05a863051cc789a13efc02bb7e0cd17de47fabbc3842cb5eec5b8d49683629ebac2b7859533c10c5b6fc0376ab80117a0c66b99af015b97cc15434fc869fb1d5ce34d124f9602f164ed759988273b71f264c593bdb52e370ef6d15a6badb5f6d61ef46cc8cf1c37d8ec60da438287a29a90a7729151047936204462be83532831011fb93c28d900c340054d29e0443cd10dc4d307e211d4fe76f1769868228a202499a3782d94b4ea30647936e2e1e75361094f1d371cb061add4e5c601d3d30ed4f402785860c1e5b5d0772ea06723dea6c2648f8505719e01f114239c309f1e4fd70d38c6c718e38e8cd108d96331229e2884204a7fbbc0dd6341b8810e6360f05438468a676396acf0a4c0849210a00d9ae6c02c348547ee6fc4d4059d7e09a98271fa5a309e5dc8e8d885c078767d3e1b302646c21821d84717921dc6b18fde233b0cec2313e86f45ca41b0d5288368a71dfeee607c10f7031e3f83a1d32d076c10080402e1f81c74d38ecf41cff13948040281365108f48b39ed50fb877b02fe018ad91888cf8bf7850e6e0989a2c7b8ab801b6fc036d770792c8ca5ea0294eaa1e99b782df4314f27e6b2ec904884cecb09344d8374114ff449e289529c7804fdede27e058fd908de912a9c61cc8dc131a51a79037ca4293d8cc35395246a0776f16cc892109a461ed8a0290c4a5105b80fa53b600cab91288a23a3da0ebefdee0e8eafda640116220474d185e0876a9e0d223c1574c38503eb98e14e1658c8911ea1e30b111d7421a16757839b29be87e8a0f7d84c313b4074d07d88f2932850c6f711ca7046a2e8710e82ad40f962abb73a1263a63b12457f2fde81cf1e218c8103ce2e4576ee73c8d18644bae698afaf38b6d79b766cafcfb1bd6696d7624fa49f49c7ebfa1caf6bd6decdb6f1c36587d937ee09f80728e60efdbd18974a5d761664a9d063a7b00b15151229c21d982442166cf26cc80b9544b82442264d0f63249481333006cb70279ee81bf095214c8e229ee87503ee4a4d033d2f1744af31202967ceccd900bec1b341eaf99745efea0c620ee56a45b5913952b63ec7fe56d987937c68d2b4bb992313535d8cd189a92a454e4c3d2df8b064d6297ad698253e10670a18a4ed41a7697733270a750f3953aab65f70ce8f919ba56645e88adeb820709541d2af9b421f1daeaa4c8d892729e2a94e51637030e835c6c7fd968564bf9e591ba2a650a8c65429e6eb4d4d12552f8b3a451f667a56d1b3d6f4ac363d2b9290a43367c9c489a9f879a9848b2bb84de03a299b42746322fb756a925546a22a8d2994679de9395b39ad2b9be8af4bae4706c58bf697564c89827c4619eda28069fad7d831ecdb89acae6cea7165d3276e0f38227f3d6e0fb8a61e272727b27a9b8f183fc94262e42b51d1944df2af438fd77e23c288f9891fa1bf78ea228e1118d7b291181488a8f9182418390a26b44721bd2875d1d3e4bd50e852c28726ec42e234e939e76d02ce4010d31ec63629b32d47ecbae1885ae8690f711d888a381395b8e349c70bdf952f75b49a8849d3c72f9a5e9a88d33a629a881375ccb4c8992825b588c33a6e222ef44cd3b6177c34b4881b40671f0d4499609864e248d55c1251f39349ced4b902ee680ffd22a69870363568116744671f2d724f0b2458d122ee88861b88ea5098a4e7b57e5ae4200bb4d5459c9499032f10c43e50c96bc9c26b9917715b47cacd87ee15b8d61a98789a558a989297e959a9e829e117f134a13663968069cf6cc9495b55269e668cc139352a4ebb9c4a31313131554a25f134654e9653e64815ac22a2e6adb85740244ac0a06b31c6186384333344c4537c0d392f868b869e6ee8b9cd1a9333e2b044cdb79a4034227d433aa1f58350ceb4839a76502a392d2425a79d522c69ee8038a135889e4a12e572899a577e1275b3ac7986569a9e3586d698de5873562184903d968ea4d3f55995dd26e5b66dad26513580ed8a1e265b92cd66db98345c496c636eec31071f174d68fa71a1863774119d6adc84132d3a93f049f97942b6e8a532509104246d3390d84fd806c16cd133c9863bb4c602510dda84ffb86883101a1f72267c524fcc0c4b1a1f72f3d9bb0ffb705b4bee71d18627f4b45374157122b86db395a20f7da780556ce2a9e6bfed25ff4694b80390d536ff90073db35acd7aa8783aaf498b9583451ebeb0315874b75db1d56c4920ce644d9611b36657b4cd4c4895e909d8f86f057bd0041c9a15cd261fdae9691642af652624aad66f40aa82d07c7a21f419b224aab3530eb27e0c60a00f9d091a6fd89d02467906b5d84289add824a69eb8af356ab8b8749740e0d0af2671a70b2d30ca0f7919bf1199b897fb7b1cf70c6a12c0391efe9528f89cfdad5ecfac86850547aa34a91ac5d2d48208a226a2ea83b0f0d9c0174208215e5b52a5e5ade66600fc45003cc3f55bcde9f40e743ae96f5b628435bcc18e5469af3686c6a3f1f75436e6a1ea69944a9ac9748c070d3bd9b6b16ab61c244994c4d4b624a62015d070536b570b0363615848e012cca013cfe0858c41720626714b82c7ac912a938fecdab38dc6017045ca588fc98776d249398391a83a6d9e8d2546198b41666326ab46a7d5f4b141c7a6fb69a1736304633bd1c6d452e906f51eea18e38fb6179c846703bf923e7ae772b34411527e1235ca9b8d44cd8dc76c12476435e288ace0f6b2d52401bf9544451d4ce24a310d18671cb0a7105e8bf651963052a5e5ca235180bbc9ca2294b5557ab5554b7f6f882130ce95677ba95edc4815766fbda917bf2b6d076d2fd841db6495a1b63656dd815328436552bba04c6c98d48c01670c30320f366fe78a28e46146caae979f29e2a9feb3bdc8733309afa51e7333e3668d44d5ad2646d76f365b12de76020410cf30278b4c242764b0c2c66c13899d89a96edb36241b2ba608f0fa2d494cbd3648d1aab9aab754c4d434c3144d333348d1f5598624a6b624ea55069d6ea3a9adca24a6a014cad082d796c4d4ecc663628c279e6e1618cf0906c41f3e575b1b0dc633e3f53106f8b5f2d49e8d26a6fefadaaa43d77f06272b8f54c1d5c98681c8a289a86969f9965b3e73cb61ee4addbbe538679a56371e30c7fc62819f0d58c4035044008a084011ef4a1d80634e16c164f8a269cb225d6b76454c412464e8026f49cc770536cc4d094ad26e46e5a4f223695e4bfd64b93c6e78db048043888679aba1c2311ecc8b989254c453cdf1aec0863e79576043d74f1b88c4ebfa592355a49357d2f67a393385f06c0c012231e303904562aaf2010666c843d7479ed82355f4f066f341af5dcb4246a77f2bcccd066d4a40986ed0f600fa207065125dfb28c716173bd3b8fb1165285eae1c3f39ead4cbc8b18bd86a4137d1443cd50d40d62465ee649b018f20613ed2f62bb7dcca415ce7047c76a78053f070d3b48353747ded6c8c95a2de4ef1b4c08315511557f51b92988a49ccace6e6645626a6ec13f03fecf18681d427e03b288fa36aab7909de8c0443f14414fd63bbfc132180176d19886c78517ec2b63cce1dde1123a5c05904b2e52bcc4684681fe57a19b709d06bf9d12cb3bde83762ccdb26406f637ad003a9fd047c47a44576269eea7fd86c65ec1454c4d3167007678c683336f0c6e67aba92270bb386cca1ed103bb47daf051e81ac07c8c7630407c54ce15008c07577005c476a2038017050b87050cc2e82ebe40fba3e001c14b085eb24165d4f04d7493574fd105c276970ddf685ae477150c413d76533e87a0070dd1482ebb627747d105cc7c2c275b24d5c27bbb331ddc684aee7b80e7f00484c612843da00066c8ce55e3f014f51ae40da46d1f6a15bc992280ab46540db1efdb152581928e06ec37824aa7ee33a1dbdcd380161d7cdacb5d65a8be17ce937a2fd8464acac883e4386e82721d1411fd131d12fd1af4824ca9d8eb628449ca8e1448d2e1de593eb8874e94fc0d8c658293619b732338e613677f92b27dde7dc57e0458797cf20872f398bf14fb083b05bc86dc75ca7a331fcfcbd08628821861862aca34d335fb9d3a1a34517dd90d84efb2782190d821a6d4d781ee5f33986b74f81187e3a08f353fe7e7cbee51f27c777a246e3ec448dfe9c1ce572e3513a7edc769ce49c8148cce5f91c3adc92001d3b06e2ba218db1c57874f21662f2f8364f50ee84540dc3709e40646333f28c8756381b134f33bec28566e40e3626037be819c6599978aa0f7136e60d183b0e19a56fcfa08c5faed3d1f72251e732a1e5f09fc412638bb13dacd112db191c1039e7cf98f393afdcb968dc947194db0c377945dc9301656ca2dc11e96a70bf8c3f19fa5c20f2658480c83973b9bb9f914f4057ce73abc1d8741184f987fc56fa26bf6d97f1036e0b20a2c31e42083978954beec736bb2322d31dca6776a2466fef9ca801b7d2bb21ad46b989eb7434caed4bb189a9b7bda4a470b7a7f6a98900ee8081f16c2fa563f9c513ce87833832585eda1ad1230ea8e4216e5bb25ddcb6711b4e3c4d56859975334bc6c8182962ea9253c4542731de0eafbbe5cdc6c6c09edceba23177c2c1ec1027a63eaf874a608b72cce763633e9fcfaf544d6b6fbfd1df36a4c6ea08ce261eb3ed67db6cda9133222d129de2093e9e20c6235577558ff5c49496b71a89da6c242ae775f60677937539a79298ea9c7069d125cc12e76ecec0e34bee2ca778b29acddb664534c3569359711353360381fd625f9fe1c494c9feb57c86a46b06a9a81ca4a2cec4531970b7c119cdc6d66b5c56235115ba58016d0cacb13112e504dc6d355d2655998d5469db4d6fac4d49d7ada6b6ac88aab7c21cc7a4b34bc3dc0052d019a6610e002c60426719065fbc59fdccdf88276db9c78a4142df26e04e8a0eb79737b9d9d9c3787b91f8777b99cf38b82271f8a1f047dc7d287c2d6e38308edb363f11454388ad14988356c6c6f4c0b3b77e5aec200cfdac20032088b8c94a124fd5c81097d59199c408e9903342bf44e34b693b96161d734eb834e53210c85a0bda30066d2fd3da27fae33a9128eb4831e9cadea0b87e634ad6b3343e357e5215034b55766c634487c1695c1018d77e7113185dc3e1260f2c9f04851f837b0f05833bd26374ed19e62c871bc7c61cdd76e0fe618f8f715b4d3cd58bb8c016c6f6324575db6133119b15dba90d2723a46f564404c47c457afd565349dc66c3049cd9643532060258fbf667051900c1c6589998aaad78aa75f331ba267afd4c32713290c808e9da9685b4d0f6022f31de2eb90ef46da4c98fb617791b1353b0ebab0ec6ac76afc05bcdcd869361aeb2e2a96e56c414be4dd70d496facaec75cbd89a7fad8b862da50ccdb72bb97315295bd5ed6fa182b2351f524ce898ed4f6910fd80952db1418989a8ed96a5e4bfd5d02fe8054d59b7a8c47f26c36db155d0f71304fd7e80ee26c3b9d4b0d51ee4e2e38773f958eb79acd0a5bd380274e7d4503eeb259636d56633325e0cfe1b777f5667b4076530fd2611c460e0257a41359ddd1495988f6512ba60cf091646209a9b2c7c7f8f01067d375ccfeb5964d3db48f3eca41e835ad02d1387bc839a17528d4b9705874117e42e2edd6867083b2135a7f2ccef291798c036273d83f01fac31ffed0369b78f4bc9d41d7e7a0ebed0f625e4bdd6ccc56d35b4dd76fdb5663ed5643d291316412a9f00463a8ef49e0a7c51d62fa5da19f165eb0fa456eef79a187b532f5788c2b740093b3927908286775e4c24012b0f6889d9ec8aa62d9e400f9f91ef2f3d8670e7204cb3dee690e422f4f64550feb61128824bf78bade411644124ff597c320bcb1c15a8eb0c666daeb1dacb119765803ad38c1687107259d0aad30a72b64b2b2cfb0eba4aeafa5180883817a18f3bae85aff7422059888294e8ba75aa3e16bc87a2bacc11e17386bd604e42f06968035f0e6d6e00de426608d1146040177b0e6c6dafa1a6beb4925a992afa7873c516a219bae7fab2b559447a2ea312e95fe8eeec8b4dcc961f25631ca9ed294229e2a8f54d11c89a27487d4f5a524ad42e3a84e4e1554091c709ef0da60f2413f3fb310d303de8ac88afead56d3c75dcd2c64feaee2b7bf1512f0e7d783cc5fb831713d085cd9fba82b1a04aea8a43bf1c4138fb87a6c0e427fdfeac399e4ad8febf737e2f441bf99e43198959531c9fc561b27649ec6c95d3912550f0798964e14de70138528501dd992aafac921910525b0563447aab420350541a0016b45e51748c0dae7ed31987cf5c41316134f558aeb70353993a45c0cb6b2d79223e0ab75e56801d31da9d2b2493e085c6987ab18a9a22c2a5593e2c804b9302b7b71d8125854125314e7d70adc5156d75316c5b1dc1139e370d3f4eaa902a6068b61f5f45c5f6811079aae7255a1d01d5684d4ddd543935096c459c0dd9553d3f534d31a89aa578e545d3d17cb0de0eeeac110621876c96dd877d0913b40c7edc5e400fa791ff433f774bd8f49798880bb09d358f4b43a7206e80c6e2f4fc64f0c818c0622a3638602c61c37fc800e44d043d79984aeef507acee4e4c82be7cac950c02be7ea792d35eae15d3dcf467602dc82d2d5b3e974dd9a74ad2e004257ec075db11c74c566d0156b4157ec045d9f71979278aa74e7b55c381c14b06d11dc9584b843bf8d89c78259997cd8dfdf2cc4b4b2f7ad6e4402b4e41e1679c8a2dff612bb88a78ac55c3d12556f0da63c74e7eac11d45d2f514098474870b1cbba3f0eab9bea8c76ab02ba2eab141a61e2bd285155d293645d70e83e98acd74d579c34e635674c562ba1e46b913531dad2287761153f0095d6fbaa35e74ed2be75a92454e007ce8b8ed80343027e05a724f8b238ca1df3601fb18b8ca00be1161e4140fc2373faf6f107077f560311293e97af54879f5743dad82d648d57c3db5912a7a9a96f5a5904d1c2289c0c9f920de6783d4315a9604a629b07ca8a4ac92d6c124764cd18c000010009313002038180c880583f1704422e790de0f14000da1b05078521b46394c216410218480000c000000001000000068dc5f0be7d9c165952132ece6cf6c51687c059a64928acd874c2224f9e9efb6550d0791b94d910a5915c4b2ab46b316839f469aa81d13e6a7e0c5a24e86bac3aadf993d6f561df7b5e42be2b839819bd27dbdcb538f78d93c281bf00715ea954dc92c04d44e3748676b1f61b8a3fc2f8a0aebaf2895bac1e6405ece8490b5343ded7829de5efc80fbad04aa70d009d423e7bbd7d43af39433425cf7be4d211b87026dd9695853c5bf436913dfdc86bf4cf77f1a12b02e7d2d04fcc611b491fd19503cbe377297b04f72d15b4312261ee1e5d2c3025a3da53116b623136ec4164f469337ba63909135ffb22e58ae26ef7c8e25e028084f201ca759e6c70e907381f16b5898080e4e366e029b80ff68c1d15d1025ccb898f12b09a20c774c93ec8efee7a76b60e64f5a5c1db84caaecf9f9e83e3fa3a0f08ae6b778c426401079d8ea5f6bd6dacd81a51994392cf42888aca23f3cb7727801843fafe914bb46d95977ba9564709185fa08d4f0aca4309956d1fdfacf42f40f1496f906f91f6ace29bca78d0b8a1eb7c4166b5a8a346850f33209f10836b2acc1cc23ec97b9cd9919072c81586952f1c7f5b7068aa889ec5a432fb6b051f5c7b652727d079d2399f733ba2704bc3322fda452df3cb4e6e5b913f79ed3fadc920a6238ab9c4fa7d04274600c8e7c7eab33992d0072bce74a692d51e328272f22d560726d9773ed2237dd9bd3ad83710c21cfa53e528d3e551d72cbff59ee90c58f3d51b5c14118abc4d07999e82c35eed3f20ad2e594ddf5d3f93ae96edbcbadb3844149dc35d8a603a56f71b0e10494d6bb5b6ba2a0dca092ac9b2fc36521ac716510ebc9c16601a62a13e91a1c4945cbccef65c1a11a540cab23c5c39af49afee5c2733ada46d4cd3b8f7874eb62ae52ef80830f99a89acd2d8fc8d2610e8fc25c759546fcc6fbd7cd359c9ab09f097147a42be13fd982bb14b508a15124489678eb38b3ad8945da1295a886334e4de870de8212a20cc47026492a3da4e34b7366d34ed3380d3855c9113a3464b45c7b6457a895a206e36bf98c8e1d97fc530ea5cc2320644a810216d5d9dfbeee75b8e39b9ea55f20f8d90d4cccdc59f14d5ed07dd0819d257434414b3d68e61d3b71ff611b7a1e296f6f3c23186710867fb66c6938043ca21484582de2a410159991e819f56305c10a2f9887261cd641dc6a34e1b0ab81b2a913c7cb58f661d8114622d005cceac09219a3ae5940764a84d0d437ffcbfa40baa49501746923da101248104dfc7a243284fd2ef54cc7b4c2dd38f68746e199533cce4af748b0bf2ffd12b150b2fa53e79dfd0996d8f53a9180e06e8c9f7a71ba381bbc28d1c6f131544fc0610f281fa2b099830ee01524d069ab1a4d4418ba05e17c0413b08c6e5e3950000c35a8ea0c6a99a69f07fc9baff1d057d0590eeddfa9a5592ab9b4dd17ea955bad2773456e335ff9e71f78315242033b561a42bf01df6b1f1dd15524c2257d03cfc91f67013dbfd7af604455dc1a3493d548d1a7b60105d36b099f1e21e02e7bcdad425e6c296b85f9e899189f627a1a2e21dab9eae67dc9d7d59413499f4744d94d449d82293611803626a7416c0a2b5873ffd3a8168f0289091bd076c6a98a76791f3cebb63a42530fd8d060e2ef6033c20125c783cb07a42007f43b7d22a19a00e03795442ef811114148eaa1a55bb6e5f5e107a230583394107c40ffb237090fed66dd72e003ac251c611b2c49e15bec509e870d4aa5b188005923f8e13c5dca38aa2030e02de55a110dcf36d659f69c6d71e311e0c177581c6133a54d1db50180adde5f0a2373134e382037e537c0dba01e091bd3ac0e2e0b062f5581b807bc4518a45a528e69c1e00e68856e9602d13dd8f0669daaa2b883ac9b4e3068f735264769d8f3f310d3c4a29dbfbb4304007bf61abba6cb06b4f6e837390e6f7274cdec1042bb0d11ccd25b39f5b706b313c2fe9ca059876f2680f9cbc3fcb7468a53443eb0fa9542610b909cff60eb7fa4fa0a953c27a0478801ccd7b67ea7e11947794233ac6c34c555c7f39c72dcb10e12324bfa8408d6ba22780abb05d64a3fa7f611d3b9701ac2b26a34b5ac48bc25ed461e912dc23d173911108b59f895690bd42ee732b7487e9e38de7c26ebce9afe53f252470ed34eb24c54f37191fe21351bfdc70259d75cabec346bab5dbd9e8958454cd8db946c138b3f81fe27525a990ae83f0bb51dd55032433c53cafccb4df0a1ba5db6d89c768d208014318961270dcb3f59c39f10bba13107d392f0a20f8ca95d4f53fb181d36913d96ec1eec4b3c38005addd20e837a7fe5672f46853a496d552da91ebe412535d4f9cce549875fe3b8ddd307797c3d7cf26b3b1b343a865c3ca690f2dc54821dda9c5b45c1a74ab37decd0d31d522ee4a2e980aa7b606a92a610a4db7bd428c003e397d46c0b77a3499ad82bfceae9020826f87365cbdf0f226b8cb3f199d94ac1ae686ed9938b6bcb772218176dad9098e5ae31574cc2df59b87311f4e192930f64ee70ba29f9b53db929dd9c4ee94953e9695f4a8a04c49e39237b6fe64b585fb8749856c544c7a746957369bb0e926c8804df19174cb0f07d4fac17202fefb341dc98595937d3c8ed91b9cc88aaba78910f089d86140241dcf47548e671e492810f05d0c5e497435b32fd7e58a81fed2dc25fea76391eb4c3b90b9128049aeb049c3e008da36a1238d219b88e11aa0ae16a984d6c48442cf8079479dd05927a371061052ac9ea3b583e24e2c25a57f97b5b211540c9e1bca826df26ad94aecfd1c378575f92f93cfa1357f4d27732c081694a1aab8973a59e162765bf038fab47db8710076f0fcb800c1ca73eba20ca60eaa333ba9093e9a0998166da13595c6f8dc7a036ad15b7c95e44d609be36b47171ff4c7b402cd665af60923ac9d434560a4d85a3ad36d735de1b5f5de803efc3c8dd61dc15a6cfa7ca33a694f696b8998e29ef3bb8001912ee533bf7ab1abdb45ff62677f4b0df5c8ee762b6276c7501ef7cfcd6ce5991c71a457ef6a6d532e6dd1a0b9da752e10b82b94f3f0b286cc5117e79387d669718c680acac16cf980e72a4acb3cc5126ccef81c52c5a65d8dfcefb96e4435e2876993138a1ad524c11290c7188d17c9ecec1d8560defb610c61d98170df6c985d46f6d8b277cbbaf82b985d09634f9878d880ba1b51c73024949b13292087009d5cef207988b7007ff0aa22687331b29a70b2a3cd87b6328882615be1c1f8645611d1d6f3277b2738fe983115c1ba1a3b953d699047499e63cef003ae4b8f544cf9e170a8650c6044fc4a53ca9514342a5c49664c48a5bb9692e7f0f2bc8c4015c1ecf81c96a7580f584a01d5fdaf2a359fb0237fe7a67fd2b4a6e5f1c736a9bd99ba1f67c094bc8dd3e01cf0bc5cf3870036d89ccb8d3896a6a2f6a9fc21bb2de88254a2875a60fdd6b4019bf8356572d2c48bd12894e6c061945be86e76386a82eb07c26762ab971cddd7f49fd538a5853762dacb6a3be9dc237798af886e8134bc72cf0d9431950f7b9d6ecf85d991ca9294e416223bd81710a74d40f5dd6760b61395a7639be3381f93f0c7b19f6ac33f88ce73195b8a0c6aaef8f1e57d8d494002adb7c594728a4f843289d1ee09d28163584f2ef9ff8fc1a9c3399c2e64c0639c3ffe965716fc827188574e250cc1f0386b3e60998b06d845dbd21934c6fc1180c7497ccc6b3932b7215fab7926b893a505d5153537f67ab9a6daa009019a89c6e9599dbb26fd7a2f70020ad35911c039e513a2d1ea07c20a43c848cc283a0a6995146d5634daf3259e2adcbb4137e85209b8a4b263a04e80cdc0d5197cfc84e591914c41902c444d59fe9e7dfc5e389a6eaba36e34fb8ca9cd4653279e9ad901b34ab04ecff49e2c0c94c598504db937e948f14fece61f7ca46cf22d4d77b0b4096bfd9f54d3c9dc92879277644f6719ee5a4f3252b9b365e1ee4cb1239ebd11295de7721713f9e9a546d9dce3ecd96a2da0b02a5132140a73b38a450b240478c040520ba594a2eeac9d5e7ba523092cca4dc6f1dcff5fbbc429d54d656096a636ddb2f2003fcdbc4a4939abfbb713c7d8b4f66bf9feb3a500538a91dfbd6c64f06ceffc047b4d7033480178cc6de179a90c1eadb078e39de9e6333ab46741ff0358d784e49415c67321477e478604bf0125b34a9041e435af5762de4e63d090601c325969e75e58c6d0f8b970c20cb58a9578b6d899b5ce8e9d5e4fa8fd73a1dc3fcba9c0b2fb77de53280f63910582c8b695e78f0328f009b41dcd21681d8e636a5eb3941f9acb42da12ae61ef4e43863aa81b09579cab79540562338718a2f57216bfc3d14bbd3bc95da24afbe19cb2d4943489f434901798e0795c9e89885076981a8b047214b6218e6712707281746a20a9f9bc426da6d2f9c700a65e3a266c786464c84af1f4256c5f2e72a3ce1086d4bc0693a8d02c2d7a935a37fd8ab63faa2259384862386f7c44c7c317ae49f9084ae8a078764d932f886ebc93eb069ea7dc0f4c2989a19b9f8a5b15c4cca85fa03c4383c6c866676b25722dd298f37d161342390974ac3a1af89a1522ea82e3cc8d870fe4b4e9ec8b8792c2cb746303a038fd698ccb06f37f5f0c479a001b984deb048214a9a8dc354a8e0eea5f56c856a6f9d59e94249c8bc93016d149af9aac15e9288384fbe91a61860b3d24ab1651d5553d0f4bd51c2e9927cb9205441759f9ed911bf8654d2684bdc564f1344349d2bd557bef6d5b70a9a26fdbf908385b25296c0570f53adf52d49848c915d8cfd4183aa0e238de5d9130d8d2bd3158a24676d718751217679690f0dd6efe4e0777b1ae31ad1585fcbdabe78fb977959e81c87bf6a9871737ff13c619ff66bdbb058f702c117e01d30de85b089095dbb3de4d04dea4ca093c1dac104d1b5b6e7455c79bf1269de116e886a2f016b4e32f9a02b94e04fcaf3a8bd55e3f1fbffeee7966e562ec064ca644c41a2d67f17468622281efab470ba3b8c1a68f48cf82d5433ee58e8b4c0f2e9e26b81d5f251b42c45476e4ba40b50b48353ab0a459b00c608d46ba08e435c06a3cc83e06f6530e7e1ecfbad2fb781ab89331f06685799ed1c22ef16686efef6459b8ce2262d8281843857172eda7fc21f83e98bd6a021813eefdbddae5a8f5212d1a0bb6f77fdbec6bb686568992e3ed021689a716133d6962a49312c9bc10877b48b0f890bdcf496b57dad9d57b912c99e6808e35c234e0b688bbae356c45f535c80f178fefa19707a0e775143a9be5445e6469567faa4f92f9b1340d05d9c96c20119f51493c4c243322abf1f02a07a646a9ef82c4d75d7e9f2aa5f2c1b01d77eba8a3d314eb9d89a217c5018918a5acd5f040d9405f638ef58cf876516d7bd59a1b32eace7faa3000478dbc90e565e229e5e69c7a2ea118705ca1c03fc946250c5c57190f02dd259d5e2b81920a7e6a0725173877633ac4be4269fa7ef58f44af9a2c220d651e38c21cfaa9d43af6243b572114360d13831c4d0bfc5e70bc78a30f3dbe1cfb18e0ce06a539b83bd0b244852790e2ea9f6755dcb2f00f7b92b6cea704cb327c86a0c2be433e70ccb3c87e48e4cac5f3d71022d9c77556f3df6bedaa447c34d7a43f6eb202670e90ab2614659d113c76459b7180cd8439736b2902d68697bb899023d04031de6cde2ae622e8ad53579bae6dceb07841cf6263b0ce856524359f2255f542474bf3ef3a0efa516b31732e8668ee5e986696e944967d8c229ede95af0f2e285243174f0d7f786d341dde24559047960a773984e55663e9c80d3aad25f23d66334745940c87269160e663adc5a63c82835cafcb2d7f03eccc3f983b76b7688f637a33c8258dfd9f26d2ce63a9dfde2e9883a444729e5e57b5d95872171ab25f3ddb573e4ca905c0277b435e4abb899ca08d86c26e7390eac148e48f656dc04b8e51d71b355ab284436e67b248904163ca70f426c52c0568ee6e5bc33bcb343a5befcc6b09461b0781ec1a37531b021dbe120bf37499a88ff2914f1da630b5b159baf3c9661365a64cb855138ca2b889d35358dbc6f03207ba03d4310b1c9ba023d37408f521273deb2dc2c7e6c8ab1a66d927d66eb3882f0f0ef05328cafc2d40113ddd57336329a76ad6b6a919ba5e8ead973d0c7e361ea821a09487422e1169511b03c29a46769bc6dd5ba8c3ff8ecd05543022188a2d9bf5707f20735dd489a21f256399f45b32a13b651666c975bb492e71650b69825a78c783a7b21cc0c392b1efea4b3cf02c7589d4ba106b769003ac862860a1ac939380fd4610f895e0790e5e2de68bf5b648ce1638c78c81b29386207767f656212d0b2ea59b620388dec810ba1f296dc5da87da057f8e313d0450da11699ba8709a925119cb21ed85596569c0b1a518f648a1fa30ae906879338c6242cad4cdc8ad7d777083ea520c5c94b7e778e6131e2bda4e662a923f713a913121844bb0c6f74be59dfa533a3e93b08122a728e58ad70871eccfe1587448ffa946009f234575f570e2d00cbfb034d4d9b7633f285c8bff275be0b84ab764f506caea4e069f514ce35695d1b03d6003ac443bbfeda3dc89a72f10fff6a96304e984f3888babd72fab1d809c472a2f6d598cd0b3f1114277251468b442567563d2a69226385412f68f80eb609da1baaaa0600343376cc31386797af988b66e1b808a564584664fa4dc053772ade3946e43441c4b13403525a737492d7a5c7169385842e608cc66547fb0bc0f8fbf8177185c5ad446c2f1a21dfa9d43514d528f32ae85a2bdc101f59ef8db91855001069470b073743678b23ad8c3deb2b32b178e4f72e929a712c0741b8889842374640fc0adac86e67c37971544bbd9e5362d1cbb16b621954092b29ab296cb1b35220758c6c5803c15716da1e48ff5caf44e7467f357ed98396faa21888012466074856a47c16b27cb80bf95b017db16d85c4c0b94fa4ccccc0e9f2fe80fcb9225f31d2221a16440b90483e39ed8bd6bc95276f4d5c330ae749b248ac5aeab116282a82178d518571dc184888f2a1a8817847c25f0f206828a8e0c8db16b0a278fc39eccb9249fca051e8666bee105ce8cda88506845528162b1364085d51b007a8b4f1f26447390aba486cc61000d17c01d7298ccd3b37e9aa873a3ed0b76e2740a38300b179abaf9c23228599cf5aa2aac73c8cc3ae143db990c55acfcb1d1f384ab5d710b2464e4a1eb74dd8c7770659fbe50bd0540b270ead5c20bb136995e8cf9d9da15292e0d033072f7981001459dacdbaf63c0d9f82bca3b64a6a400647efdef67a4eb1d430cb613f00053a584a5941f4cb473999c05ee7e55e0f5d85adac6a4b88f7d7528593c82c8b76cf6657a5b7ae6a23904358d735e9610947d42ad8c6842c36575f1c7792c9e36b66a7529278355b105714a31afb210b3ac4e7783346219d45de23560c173d8907f6838d3fa52ee8f93510bfebb59880d1679a6e8cbea3bda388e57676fbcd4a8da8ba888a897621f758a02631a36041086844da64b73b8ee254856b87844e65f46382d4ab44fc8fee34356581cbb49d9b52e2d39dbaf653ddb1493e4a54c4812c575ea9db93663cb44cedea65ba72a9554bfc373e470ddca12d08366485f4f178ca10632aa3efae107346aaa897d7b2cdddec60d2918dff961c1cb93276c44d37630b612bb1baff0e586af6f184ebb2f399ac62ed8193674821fe1283428c3508a90cbad1baf9ef5dfd87d844c6f38d634108812712e39bc3c0b2418fb3979fc341750e5423b0650eb990314f652049a65320829b2290673f8aadf301e23de0e28688fc68b8170e7383f051441cab6d18e0d04a7bbb15d01d58cb1072965ced6d1b253666a79eb9d8c3ae058076884b88714891433d254e1b18fa14ee46c066cf036cc4340da24f0ae7e04870aa77e430f7c54c7a7895f5d8a34bfda28966423163a6fa5869506a08018bc673a0538dc3327267c8e68cdbfe88dd300cb0c071988557e52214138b0f479028adb66e44d20de7b7a2ffa6c2333b925a094bf2c965a443015c166713cd14515d168a085dd08c8d6048c03576b68ed5e368cb0c523b95afac2013856c9d69b234532ab050e9b5ea3cd93df2c51b26dc055b2aef8a885155895a9675a50a42534f40dd23a00cba9c42074f09b9b107fb45389aabd388b00e149035f81cfabee10f77b27b0973245d778b45f3c94f00c27a0e598791a73f448a270254308488c16000da4512c13bed0b59c571d048b09cd7c0125100c332a5d9672d810a2b3647cc0882aecc4ca8d0dd72294207e3753388e530e408c206ce053b4b754f0e68b856df8a4c894505f636457283bae13b3bf44c7ba6412a10bc52a468cd50b3f8ccd5c2bdae1863e0f71dc3dab48d51a4a4b682cc55eb82656662022ce23049297821381975d99f8b06653abb1282ba680619624eb97a7628e3de8e247170e4f59bb0fccb1f9c755430a06bd3f5af59ebc40cda1989998306ec2506b15cdbb6bdbc77e9988b728b01aad31200b9006ba0c5dc52678fa215b84156cdc5e00833ab47b40a0a479cf1834e5293f4b6c88913b39405f3a11b468504241a7108fc794bcdeb9e5443b4284e4523ad0f8cdeb72ac36e83392f225e9c486c6b5f73b3b49777f9549da1b273e1ea6dcda91814858ff8af98bcfb2a5ea9e3d7728e00df2a767cc40143f3443910cef1b358dd7d63b07ad767ef2b1463a5cec97e1db30c9301638b76794baf024e34aedf9a0018b464b40318e182ee2d0c753539425b5cbc17572aca33b8232850a6a108c609c15f38f10ea9085f90f32df538797542c6bb786b95aa39008dfe3a68273f997d12af8188fc670e819c8129cbff5a153a283dacdc2546f1034c3e1cb1ceed704815c1518e0a171f0a77f410636bb8afc1cad1efac7d38f1ee018a6ce79553e70c8c487e26c4b7f4aafc0594963a202adbe9fee65f1a070fce4ab463a7ec2e0c200a020f30a1bde69d755da863d990814eac658e6d4f13f45847eee989894ba622c423095bb32c49f6a389fdd15f0b78277d39873b8ef18f252f33140f1c5f2dafcb9f8e6800c6dfedf40fe6a59d5d0fcfb163827bcbc2f69194d4c589ca4d29e1675dda36a471d1ab1c56e731218fcadcaf60757bed61d80c18c445a640bc25f6cd3d43cdac0d8058734ea5e49d54caab4e0d8d87ac775d475911b1b2a1c633663bc34558fcba56885f88934dee716edc828cdfc3b5b43d3f8e3931e6eef482fa08571390984e8e0445dd13524c29a2d896768592b1191ac96b90a6c583d2ad34e37f507546e4b8ab997a30c4bb62fd23e64843dcd881f269dc5045d5e0e41366e37d349fd74c116e6339d5f0bcec2d4996a3213a424867bef53e1ad44b3b6da050026b339013534956ead9f5aa066166beefa09b8d289fe1245965af42b956e60f15a8165d0cf1b57aa77b85b50ac2419ca04a3c812ea82bea210804ee8bba2de5b0396a51c5100e9afef1a09757d93a08f8a6a3f005d4845afe690e6dab742f946a50856de390eb2ea2d1c552f4c35a2d6dfb618c7a5998bfeaceeb6639174024c4899a4f1a28cd00048813ea43dd41eeafc3f8ce22e899e49040908651444e669db02bb14fa77267089759921e49e81550a548e0f8bbc6019b0f70520e83076280ad647902492ee9d0b491926104ec6be484f3a991845aa43ef343738bdec67af2090f02425f5aab1c2909891f801c086e4df6eb45876d755c78a36fb88ae0cef2c824c2397a4ada1b5d979a0baa3c7720aa4414a67f84a3aff413f0545056be52dfe9b44f1d038e01c72ee0d29ed3b6a4efb71575e40d37bdc1034d6fd59b9fdf266d107e400de6ee0def8bb2c57bc3b093befb50b2f8d8871479ca9706631ca0ee0ecef051b6610890a1198f43c3c85b904328ab20b1ca4861361958abfe084c16876972a235a4305d9d95a55e9d1595f5438bebf1e812662dd3fe4f5cd4c7dabf1ed40500158d8a785b86963f436e1bf1345a98f68817e6aea52e936f0034c1641c06f1341854e16f64bb8de11b793860f634d32449df063816d73ce00c701ed77c21031c2bcad73a137723d37c04787470082f3b85d75b8fd77f4c5156ed23bed0b6a596d3deecff5ff4fd5c905ab29fe0a0954a041f4b1e2d77e4da2ab5e89c51aab7bbc9acb1a80ddebc46a0773b4e975cbcc249cee036036bbf2f9001bd534c1063cde71d8cf98a8e8cc12223a64dbb17370dc5aa720a2e409fef77197f38d752d71500921a6e386b0318e9ec46a0282bfb0e47fc54a8f1feb7ca2b74f88ca1ae5ed3de634b87af6965d80ce4f70d5a6a9ca04765e90cd5b79265303cb9adf64508f00ea576bdd7c141b2b6c5388047bcc610c77cd30ff3865274331e367a938cef43a8b3293b490cea0f111b78ca52e8c73afb57c895d54a527822249107a346f6ae2d3aaa7e121e88e839d9d07942c6a3082e0411434c473f4e98ce2323658a5f16e6ea306b741fef66c755d0786d1e892537cb565871b08ecffd5d7152ae989517ea456829bde74eb8ed0c375fc36fe384c33444e44f371cd8fe6bc0b2848e212d013bcc584157935cfec77c1b343439e3f341ba49e785b4d132bfbadfcd06e488a35479f44a67433776ee4c4c609db286ab8a4c223bc43f57a09d5ca89c0c951bc1f68fb3c5b1afa0265a4a4b5a6600334d1d212bf7da4330cada9877d170e179da647c6913428b88a09c54c6590070afc595d20248c8ad356c9152da0b0e378c6b2818c677f9c40b023d8a2b3a3165f5393393d8bcf56a202a56e84da1230344b74e17797f0b9187c57155e4f7fe787b2ade2a7080de1e8e107cc48f43dba5486c9bf215d4bc6bef1bf42806e356e78a3608986606d39eaa6d2b46baec69b81981813f6b8a6558a089131677df99c39f7dab38fc50fbd4db2415e151f8081662bddace975be16201e7135b068b3462d90f1b2ea238f591e1c02628c00e4f555938dd6f17c11d763e743959de67e212dd822580f6167e043eb747f75ef4a28782ec757c2ed1e8d45f4fcdaaa1f066d173cd5ec5e54c04d2f86e1515f1dd33ae90975d9429b88e614f7a3b8921a7371c5abb1b182b1b71636635a6a785a92903e6977d45628ab9b83f791d7d2926e9266e1d153dee9dace2a51eae2b8a11ca27501b6289182c004cb4efe638b5fd743b657842b5cf6013012c957c65291fb29daf2c3653d33326412baf703060f049ddfde0800441ae7ba1f3f2af976227938436288bb38ad7d6b30f5a928559c3012c8b6c5e880e90d625ec95256a81f42ac496b82530781442b9fdf3a1d44605d0157bb188d1c796f2419ea9b3a072b0463448ed81a7ca51e6cf12c2b75d8f03eab2ef507c834299c45d22b789fcaceb9d25a98837183d6388ae0e8318f2c6c411443959dc525560f6566dcae2e6630ba3d1b712bd20e57c8c4a334e596cb0bda22d20c0c5ca4a78163fc57a0dfaf6757558e3adcf3fcec82c9ec407714860370cb3226ae88edcff94d1ba9110343f32b9ca603066334e3fa6083fd4a8534fece09f3e2cffbad73c37e83f3e54fe7aafc5a6e048fbbe8eed9ee7703d87ae22ace83bf7a04ff1e9a1ca4c38e655a5a7f526aae6507f5bcf0a871bf4d17fd291772ea2280c066cef9426b2dd1cfb77a4b024e0e401969c5e871a5c2ec117808294f3957fb9599e4aff80057f162d0766cc967aa0d528fc923fe41c399e7b354aea0625aefb53c17e0f54c452c1ca7d8acc184e6ea40457a7c362184fefbeb997b3dc291327e9d02c37a53c5c89364523198ca33b7b490fa29d323ebf0e8c4023125b4fb03c8337669c0d6e0b58c4e6f7cdf3e8a208674ab9e2c996d6abda27b8121fb3ddf0b304e93e636f13b455e611b88434410b6d10f75aed4ee38efcd0ed9554f7a586be78168347bf5e29bc155030d09f8dc931416fb3a091207802ddb626347d420fdedc25806c6486011d31e94c317d2e63a440c85241fe6450d791d90541cae1dab32a50970223778f9223f1d21da63b582244877b56516915791ea368fa319deaeae284d5049b33177b2e70a8ea87a6982dfa86a266589ba22cb240abc222f1d3b54de5f76167a5116f3cbe472f9a3f19bfaa08f422814f9a8c99ebb41c9103c5ef706cf09960ecb138386985634878924ae6f515ce55cd03a5d844ab2108298c9acfb23dfbe05c3fbc316237a5894730b947cf4430f3ad6e7e6da67014715d7b27d41a3cd0b259226003263aacbba144aecb5a8ac5348cc30aa38ac85d6860e214153740ad43ad4682ba22a074a8187f8eebc0aa3fb1832a774c79b6fec5e16755ed0a8456e871b90408b48ac5460c5b9d3835cc9cb009ca320b562e3aadbee0ef1f0fff43dfe200fba3839fb4f0a4ac6dbb90a2cdc1fa91d277aa0002c7dae70fb5e42322ffd3f1270bc8bc2d05e53e4b80b59056dfc20db121c602471f6cc301b98587abe28cd8d4050dfca770bc133d63585bcc5eeeb39c2e816e35d0c0882e7d874b8490be6620c9114889d254f4ea18d2a7d4b033bbfc8ccc9bef13020bbe7d46a4089eac6e32b4085e27bb3398e4546165b7c69b38a2083ff414732c4d4f310f92b8491a6ff1082d0bd1a48f11a3465fae90d7cc65f722c742f2147593a50ea7e6c15e45c0c1d925c133e05410e42d9e6aa9dcce0eaebde775b8f0180315c14008efe00a0df08ad4cd35ae5c90d327f83ccdc32eada8e34cdd4bf323b65ed7cda416367e7aa29b0cb556f36ab7abcbdca556c8010d9d4ac4eb39934459aec424e97b2bbeeab24ea65fe54aa9f6f40bc9c2e6986da943b03766b1114ece46903e04146abd9d3c5b8f412c11b0a9fdc53c2bafee353596c5fc56d8ceb11706bc40e0d6043fb204793dc41cc596b56e4e336c524c1b5bc98f5b6df98a3a0ac872b59f0e6141b1a9e198954d6adea1f25614646e54e117041b84eb4b51d32f35e37e3f44765de538340608cb83035b0ad800b0881c11af6d254f7c52b83ac450af2703de1b59d67d02af83657617375f230424011cf4462beb209c8efdfd647b7f3eb453df84e17ea930a4201ccc19dc6c761a9510af8ca42c686ec0a115db810409e4c94bbfe9e95e0464cd350ed80f75a7ddf8680f0052286380fe164faffddbe925d0520e4ea5599339ba63a8422a575638663e48b4655933a96e06481d1ac706c45c8d3bef1cba63035bf4ce5f0be620fa8722056cb6b4a4e4cf59e210b4d9b8fb3929c159b2e5c503f73487fe1cb12a50d417e58a146a7ce9dca636ee0a96b340835cfc98f32b681e1c25d79735a7755e335cfed912b3e608c28ec71a1010c4a985f103bd6a600b52778819808376d5e1edef917a830d043eff7eb8b2e3ea2e10713e88988a90bfb4bc53bee22cc50d70df99daf79550d8fc35fa259cf31d4df82cf1d01db105cc179a8a4e8bbfcd8cb7dc03ec2ba9a751e78699286588d99423913581015d4068f951acd82e5e9e2d3fc9a6844bb454751ebd166c1c12b53661b7c2dabd1256f8d470e43b51fbe051448cc68caf8f1ba3020b3d8b6c1085807d75cc102b6864100ca0876fd27c8e15ff86f657a488ba6f54918ce595fe66c17953a6200921893cb99eff7f5af9b5f565a3ebd5fb2299c0e7c21d817c60829b7f8659e55fc45ac150068f2f89cebbecd48ddf4df2fc965e7874d88f776a0a95207403494218180870e2c364691e7aaaca82a20232dcc085e85ed7069b02916a948bd0bd6f951f1de0679fac1e3ed3002423e50b9cc699d0e11e405cf1708488b820e71a0f59290f1c85d846f32806227820a196032662dcd3259e950df0fef4b9e9346cd73d313062c4a5b2bd57c2fd8f3fed7d99240e4f937999a3c0eacdf6b9016380cd02f5b2d671fc1423d80c843a599a201054a2b663be0e6cf705ef8cdf03038b60ff4643dbe32cd7eb5e7ce3663aba6ae405be178791ad367be6dad0dc45b99c2c6ef5ddaef611852aee2a1ce609a5d12be607531ee4fe86f3c4968776c4f2cacb22a8d4953d9c41e686b417f1814a63b2b01e717f05b0b4347aacaed750d87197fdaaabc1798b0a610881f991c29a68c3c0a88cd2c9d10b404652c3bc5561f893c82c7aa35b14b14e92f30465c13ca2e0cb0e9a32816a78cbeea436a5955d4215c220b6349d784cf87e71aecba40299c0b5ee7ed36eb1532138d7a9d0616a8a2c14458042e1c25103284af69486728465d92eef01a48acc827c5da9df7a72346d498274c7efcc73c4b95f6e11e3100ffc26abfa850e4c412a9b94b7ef16242b82e344698df0dd2899888df07d21bdf65c422e7b9a8d25ad71cdda5b0b281d073a331b035109b2c96ed8b116819249e9417fa436a933b99a395236226e309b99b3a13988c923886a2d10afe18b9b7ac03d12c5ea097850c2a4c9b0f44c0b8b1f0fee6ed13744ca2b8b9cfbd9c87e7e8c21c51396b47365ac75554ae9df2096ec9fc41a52b1cac23622ad6f6262e090a01551b31ff5b0900169f6e2d2a3e73079153f401da597b02e5cd900a945411ea595180a6eb5a264fb5b14fe0556a402eec283e3bd650e502e085c254cc386bf79ec18d7f4afd616d7f0eaad1fc21a9846dbc92c195e5819da9166b6f3a513e8f21c50523620a0c9f738b323d23424eb6526aa259f1a8d03967c6d2688f4c655a0afb0b4e94049f551ec3df8cd6bc9e687493014290247daf4215e0937be1bab8896e1a37e24ae0bf1ae5cdf3c4c34b44e62e2c5be1332e56088a213137712d6ac805f8e4f1ca65a1234bf1cab78a62829e87e38ae384d570668fd384e719ab41c687c74bc6234b54cd0fb625cc5346599a0fa6d1c626ada1241dbaf4a2a56457298bffbc43d063a3990a980452153707e0f84624438824cddf77c66cbd3372c486db2f16b345ad10dca1d6fe0154f001eb0e83bb1f3f55de592a05f2ba62502740d966c7d89a64ec862f0b68e1960a8a8ab0cbef3f4cbd23bc296200d4fbe5527f318376117c11edcbe82324180aa30f072a127d01aca40775d77dc17aad0409bc1fa1dc735793622a1d6c21820d3e2e86acbd03625a35a601c554807a161c6833c5b2a3eee02bf8b16509d3f2186936163971a48a85202ead72148ffb69003740f71a1c15e5b9ba66299b558524d5429c823d1845f263a19d4a44c8b6b6344760e8b35d3346f6c9b26f2f2e29ef9b50b661fe22382a61af7bfdbe5623ac9dcf71e7c2d08654741125ffbdc83639523587cc27366f477bd334e2596e7b486ec0417ca43d953fe18b7a8d9e13b1c428634034ac57464cc699f3adc1fbd9645a7dd2d61269e9a05df6640a218d09d449109dd6a8c4c76823f2303387196bcd53aa4b434c9e9709152864bf6a0efd3f71a7090d811e0963e5b262071171bc1b93640ed2c6e847c49f2d20767f6cb3fced8a815e3ec7d6b2dafb83f7c29125b6cb2c680302bbabd2076cdeb5ef428d5991f91f61975b8d29cdbcedc9ae14793a90a35c74be952b134a6103411f8bb38cad6c58b4ffbdca3004b6f3c6693d54cadb92bc0b14d58aba5c0b50e40aca10e878171c8bab09a0791f69efd6c8de118fa29e5c64b4a322e0bda3a5e5f4e11344fb3ec500738eba6842e00d133aaf72a418f5ecb08604a8778d1ea22483096cf2df6af372785daa220cb7848b132ac2edd96b3780feeac0961f42371487cdd12831bec53f527ce34fb30de7890c43f425b4e0bd13e510a2efe8e9dd7a380296d55c65d9955cbafcabd7bf49148b5a74d24e500c757e9a930dae31efb8b2d312ea851174240ae5d0d50c812017699c41f33b86e468f9f69b51ae31e892252515b39d57c67df510cc2f06708d001b803c3d717d945c7923b941d8b4e3b3dd9a484183d6df4efa7c7f5fa51c5857609f646c7d9b8fb12c64b33a21f83d7a94a0e4a36550ea194d8ecacc09a8de30c556c1f303a4867d83cc4ff3c1e20a206ec8e9d2edc5708c1a647c2bdad13cdf6c740f4b03f803d1a87c430f278a20fdaa741d0b6fe14d0f4d3e06ee6e6b3d3dc44b7834f8cbe3cfa9f90acc93ba1bba0e98d5f7a47ca9d36723466ad71f0db00030440b4b642e19094f44cd1222a0caab1a1983a3b622c780861234db6c612f4fdd24d651d52ff527eab5e49f8a784bedc5bc276fe2fbb3006bad604a04f2486882eb97a0900c697dc0fc5d2e47fdc23d5fc1fffda1b6f655f116df35162272d8781ae26604f8085f1d1391e520ecefb182cfcf0113271c86f46220dce4c35b8dc329665b7ac7f185d281adbb9e911f26028d616db1d722218dce5429d14205e1e5cb650828de6b91f0498edf7eac04515219cda945994271846c40524d86f03fb2b90a60056a1acb501b95acbf50e14e87608b130af4bafe002cb1dcbd11177fe120a1d656cd73310fbc9cd0611a161bc8816b083acca116ad00c91d0243834c6c047399760a106b8bffe9ba51be9d606a176288ff4021216a09bfe7584f09d496f254e0a5fa818d6d9af05aaa28090d69dc64b4fee4bf9532e694ef0333465620c97cf3a999b57897b747da677b7c4542a617fb256291636defde8c27c0df21ae823cec230ce8b4232411890cbf2a8d005ffa7fe17617bb560fc0287647b59dac1cc67d3a4876fe579a8ab29afb833a7bc28e341cbf4eaea54d1aa54b4d1026b4f02037be8c7f1700562f1369c259b060eacf32f912aae18fcaee4d250cb67c5ac336fbaea4df852ca4ea15b5bc0a0eab2431c441d17f29fa9ea526a10c970b68eac5cf38e1c86f6ca0996e04350394cce0cda4c89c00fe0a9515803d718459a4c31e6a44f904ca93925c43177faca79726002b94c30779ae0f37e9d3a1c7273081e982259393012b723902015be8fd6535a21c44986e2632c18ccacdb6d7ff9983d305c6356e139356d02a6020abb8f182de61363304ed550b6006aec3b76b4df9ce522c13a5e8df9f239a0b1db4b033bc2d68d9cba249284700e746bec33a96aaf03424102ead8f41dea713885742a6c16923c0c0b95ecfb0a0c1585dddc70fc0a78690d9adcfb2b3773affe99c8e6f405796c161804bee72a3a799ec03fa9a5779a17993ceca92c2da76851e8c458e58dd403b9a344b35adb724252bb74280b11310f98033175bf68d393525702acd45582944bbd94425b95f1b71be44d4def999f10f9f6e756024fd54612418ba99f9f124188f949c1940762126f0287f8502bce793ec1b36f6f900a169cba52286686ef8c9e2c071d2db18ad088bdd2d9d7e3ce0f160bea0013d4afad8e2fb5821d91634e20be39ab459f4d3d1ffcd02c7d1a7b117107068f06008f837c28a80b5d4ecee2984cb016454f8abf6d876e7173170593a51fc41f8f4dab5f2ea63e0fe306479a53bba2c02412c20945ef547180a3ba4f1bb0d7ca64767e871b3d520a6ce09c545019512485b22b6d60e855845273b01f0fff47d4258bdd11f56b1ac41f109efdf87b9f2cd6f9bb02ac4b0787fac5ca8a76e2f034538cfd3a9dd3123ae0673a43c94759d574c0eb1238600990d02b0254f445b6a0abe4a71c18dac08f388a498f1cbb02284ac88b837425e714052b6d8d491e3590fae72c5e60a2936b3829b14bc4766a8a7e2a49cca104e1877a1e12bd4050f0b930abe5cd9dbda9a0a347909b7a144ae814e9eb69622a3eb2012f6087d88f6ea9bc267d7f7ec09a9e685d58151ef63b1591095ab61f990beb52d671ae97b270687a7852a040fc29d80bc3db1d0db508eb6cd3d9e6b0b3b1e10cadbedbb360d3de100609045afa296c3680634cc50fa5a46e7755cab35a40c334ce92204c5340172fd39f59363a4226e4db9ddc2383ebd1df1a0690cbe6904bd8460872cae9c43dafe65f9a0fb601f9a88c4c9090ab49bc11e4d519e1044f5e6092bc00db3c07e2ec30a721a2405e3fc1dbed214ddbb5bb51cc3428d7870f847c6cac405bf4bf3acea871213bc2de52c8f87fc437cd168c614b121489d45bfb03c454915ceab953a5a335baac00486743edff772be7f1ca14985a544cab720007fbd485b7a7b65b3e0a705f2477b26efc1845e355b460fadffc8558660ac8871d217bf3d13276a6302c078989ed599d79e033ab58a137dcb7f48437d24d3d5c3dd9d0e134a5423b865af6605d346218913c998c3317fb8d423d073cce33eb261b1b24ab9297a4cc03a459e8fb874ef31e5010b4241db2a1444071e98c00c465f04c52b9cef0818a14ad5cb029f22b57597688c185452b97a2abd204bb276b6c4035a6a772e5a4b0811c1607ce35a6209b153e70c05505100858b9aade4858958b578b8d3d0c28d56535b9c0d1be36cbe6ffdc3ac5a7c38cf2cb50899d86888db7b08b1317e1bf1888bb8256247858f6c483a20445110e6ce571ecd0f5ea9dc8f83d2e7b28cd95816ed3811d5173aebeb3194158216c43439b8b02c493b50e06ad3c88d0d50409b102eecb596409e71fc2776addc2f9c3491d9312e28465530ec4e89023b69f1d2ce783770c70e03e3f064f1215b510e4ad2fe40de165426715aea9107d9d62a8ce849c7f33fb67b337173590ce30802153f37345a4ddd420482689dfc4b7693463f01829f800e4f7e1d546b2d70c9895cdca0e559bb0175fa11a390741546a84398921a14935640de794d449ae8ed1773b5486d69ff07627547d13aae166d634a0b8bf7046feccfe610054829991a5147c96722558d7dac58b562d2323600ba5b1ac6d750562b70e512a14ef0082de3086f2be05ee83a03ea3799fd0bcd5cfb08580eacf2d41f14f45a8468d84554764eaeb6c00732c0ac30973d00d8880538305cdfca16b1d44b32cc3a1440863283dd75e158d829d32e721a8872baa0229ede57d5644f8f5eb087dbf4b09cf06d85db823b435daa94e4604695f2c8e78348d2d32db8d14527ca4abca053dd1c009345bcdfd1cf41461232193a384afca6f281364a790fdef0f26e29dc3af8eef86cc5af382e936f29115f7f5d43682937a95be952b9811f43ad847b03d68ebec82a70cd31943e06071442dcd9819cc828f1ad59a59f6300adc219da30399d5a3668fa8b56c7498212d4e6bc6e57b4ec2dc516219ab0e6c3d091100bda00b2c8b6843bc1afbd8b6ce8c1b5ba296c33a3c1afadefcaac2fce1dbc87275068fc2d18beb33042c185a1e6278fba275d732f202ab3a969a2abc20ae61ab1c772f9996d4c0d097a37fb2487746ccfff1f9100cf201dcdf46ac6a50a0511b2da2a83afbf68fd801e752b2ee63e17c5fdee799ddd47692f1084be4913c8012fd110c7066284ae0b8bfa38672d6513912236aafadd1f14626ef2eca227d27de17c17ab44046dcb83f82f6ea11c6dd159a0dab4c8293f108b0470f41d188711bfbc1ae9c6b49dbc31724ff84f56b7bf6c0d6c57f1ad8da249333d063bf211ee061006b540250ac19881fc0a9944f0304a1a7d4d87fc9b6ef7159af517157c8e031f34a7608a41f942372f3f8a5ded7783c324944dc4734111debc4389951ac63717256daa36e996f58ee6d78848ff302b7e1a376d514ec32d62bc8df791651052f30ced8034601acd6f87f108576ce08ff9620cf3073411f85ac71156592e7a326af424c8d7c9d2b572f4b945087168213367ef893f98a3871f2854958038517540e15ed0737917c04e16b05d8177118301187b77106c8afc7f883294a20c606af2aa10a90560485f7671dd1966f47e1f937f14baa249e2c722540804fe170cd308ea7e0e919bfbb82e7d3a481ae1d695260206249f8b8bbeb2a60b57575cf45f3fb075983cdf78f2d0a8d233a51d901ae66217b39fe23ca4abf6e06923ce3e8d99433ee2a51d25234c6d9c9ea07fcf09a1ac51b0c43d29076190d86b3b215c40241892c6f47949510e29574a93754c43cde07291df8d0bc7dd80f43e3b5491f475a0ac54745eaf9c07b44f01a5f65b9b09f1a9f4204a6a59aabba31762665034591a52e3556c220096f5c6eccabbec0d1bda685aa9a2b886310e9cb01142474e4ee66c13338cbef19dd9e847a83510fd79aaa70861f2253e92a79f336691a4535097b34c086709ba55c9ac71e36c12942868630ea7e04689e755d8488c8426b9f3c22826b542921562836647b842450abd5b4172e50880135f3484342f1ae0d04caa668ecccb530246588534de22c08f29f01dc7d75e382a0f95fac495a10a466d3a5463f6b11a38fc1b2df6e880ae612e2f6171976753d40979569dd59e8567fb7cc088a0760476510f6a9aff2240ff517b0f376d7aa700dd5ef2f595c5022e49c560e9432fa5e735a9b7a49c921a5d19f18a7fb92ee6f409b17302474c0915d317c35e5a92b28e6b08954596c934d37281302d002757e82eef9569301daa24c122b7bfefac37c63b7a0094f5aa7a9de4134f6df4e68a936be7be24ae80ca14d9293edc2fd7803591dc93f70f4f6e058dfdce6b0be046971ea698531f4aeb22a9db0b07dde21f87178649bbc94b27538ce71ef0323a3b08bf911542e8ef7b15551f50369014abaf2a041afe52280f5f4d8af249bcc881b2cd118e6d428a04f018b2728e46fb20425fcd519b4b15ac6cfc40959cde40a9a754fa1e7bfdbd3c5a96b3dfcd221748d600f985e206f39aa77c3e727f9332995f28a2a15694b06a96861b0588001cc05746e7f702f64e7566f410f752ac248f0bfee51866c29b0646e02ddcf9b94ebc8163704090c8db227df379470dc112e77cec6f79416c67c02a85813a2ae74a103ee21672c5de02dd42a96a16b541aa8f205fb233ff2e31f3157400c897c7045e880a350e0f1d55af96be7ec38942a50bab5a018c81aaca6f7a2c4f82e34406d78ddf200cda9287155ea2c7412c354b351de6edb4a7f3a2467fe2cc8a6101fa5489ef2fe75f760fc2f8d38b42c858a0d9aa8d6fa92921b8cd38fe69bb8a6412bd71b8e7f1445bcf43d07b47baf274a89f6cdfac7396ecb3878a50cd27e303f5bd071b8d457f66f5cc5b1dee317f10b0092615e056083e715fd66f95b3f667348d2cf0098d895197d06d0d43715288814c5ce9dfdcf9b10e38032c7afd3334363721aec620d0f81a68ff3dd436fb9afab18f2e24044fc85479b56aa0357ad09104a689a3bc62193b5bb8ffea513181df61505cccecc0f9cb0a19b9d541ca3865bf718135f367e98c89455001a64f29dc5f0f252ae3693182fd83f5a2423f71655d292fe41fa2649130070126dd52ae6165eaed060e21684efa0a9a80cbc58d444b28b5b9e4391d83ac7f0050fe8519ab0a8c07480219019470281b153304aa14811afdfb3e4cf7eedd04a1b86feb45e8b3dd6acc5d0058de963bf22ff496c98005dd2ce5119712ff4dbf7020c26cf65059f16e6018487dab49810406baacd59711dfcb323b5be27ac0ed3e9435660d08a99d20558c6eb4d22dd519c52c9ced7e97b878cdeec08445cfa7110f6b489023514850201b500ed5f240ae20630d50010034dc588ce2e319ac257ac8a5631a9b39227d62b6091573e15ff200463da1a8ec5e0e27a5c4cb45f7f4eafa2011c7edd73f370eea29e30d3d5d9de073aa7ad5bb46f6a4885f45fff5b368fce93ff455126a6f89b515a9063ba87ac89be822095b117d974c60912d00c32572776e01e207408e2d3a4f9bd65d4652e6082af883a819549a668411ce521d058680f7ad556fb026ced79c9f0f0dd11e55458e69adadfd45168ad2ddcc4ffc474c6a26c28aae0f8c8d9f4886935179d748aee41f0f9fc2135f141046d12c8b9acc94b9a43c0471c0fdf867d7c938c99552d850790a02e5799e1ab006796456ed76ad7ad7fb47b025cf35035b7f71acb45d2863d77c116d8b85a1a6bfd88ace8a915ada157f4fece161f427dba417c823ce3c665512a3a8413270efe7ce60923d3c7007a1fcf2f61740ed6503152a7305b87a93ccfdb4a42aa8295c9a1e9f82716cf93c0e072660149de84ba5f684a83dc82cbd3368b32b4193f8a96967683e23d93d49764d54293696065530fa88b1d2a55e06aea1cb46b4a15f27efede0214d4b7c49e04b11eb5187587991dfd0b8cd37b0b427050dc7fd2a9cc42a4d577a283d86d0aeb9509b29fa21d13ea16805e612d90761f18e9592a225a6e1884e0772a69026185508bf2abbd6529a7adbbebf6b6596f9301da80a82fcee7dfcf25e8bbc504a3a818375528ae538841d3d660175bd413f8fb899b1866d8b7220993c85324f73c16343aa997f13bdfefee1e295f178b76c9a11606217af34fcbde34826d5d227028d9982808b8b7a2088959adca01458b125f10ff37d102e802f76e45da6a60b9670770a350dba820ba846e186c7d0cf44ea1233d1a12fe92c592842b66c86caa9717f7e14715f4993b707b1a4a414fe3f9547f2a109c47fb28c9beed0e62dc7e900f49f1d5e641e0b207038b3f144126003a871302ec644c3bfdc1149b80cd668013b644788651504de6e81afc55c4a22c96c3f67ab8c6b24cac09c30e734250391987556a927cc16d4f72f2f0d25e7d5f8c7185c5951eb524331f146afb17747a365d70e5960f6df5f38640f11facafecd0d7c78d43682bfc405ac6a4c5ebcd5a1ff187a4d06253ec2b20ab3c9ba9014a0d0d8e4c243d8574a362c2f0de3194b969fc4c633e1b46857a2302fae1b70f471d3a4b90763ce3b689ca301846dfb3c4c160c1bb811a0d10fd9d0d8c3571ca1b4f915ca0d85aea89f6e279eba44f54e853bfb001311f88ba0e475d5dd86d4aa4c61e54eb8b7010c6d75791f7084df892c487cc1af74b408b9000ea5494125e7b31af2a6e9827ee5aa74408bc3131da72b25d15730d0caf2935e709fce2b02d20e44e8c83627864b69cfb302bd405a02677980c2c8fb234c3cf560f42d4126207a5cbc22c2efd82ca7078a387b14d15c9470a1298455e5e9bb0235f908cf95454ea1360131e581bad35fd139f26022560cc9ddbee743fec0793694745a335614083c0a51a3f2a96549a528829367dd8d295c0dae1f407599b4587c70a9b8a71c3eb3c2c1cbd5930456eef0097536fda652d8a957f6aa32ff9816068ab813120a5b505fc8496c6488eb50a64cbe825db50184bb0fb417298399fca47e2ad5de39919a926b2636004acccac2a4d908e328d997ab2617999cafde73cf7f95243fe21b9ee5384a8444053cbb8ba5eab5181d97b9fa5eb17ed561d56dece9d21b426dbe050f40d1d780cf61c2d90148be57f66f9ad5daff84e031f8237ece69c5d44a0f5a589b06b478f7dba3a34e5e9c7642742dff3f3467df0d3efed10549d1bd8a37769ccacc173ff665cc1379dc36eade015f91f8dd1c21cae0e9dd3648509a319acc0cc8ef07df7fb5eee20ddda0bd5a94f5659bd14489666d6d713d44b996e8304011a7ff38712c4d0a81b529b241f65462ea4292645238b9391848647a9d34726eb7162c10ba2a10690030f80bc963e57113423129f3e8cf825508d62c39be4bbde6610781cb2fe689982e5ce0419d35eca0bef6fc466187015bb03327ff82eedb14c59fbcced7e7291046b097596d24842357e376e66737158a4083ca3783e255fbd0f6869099cfe8f3728f17bab1d0de81d717619324e7aee583e96f0adb92baf3c9577edd67a880232013ecc6acf581c74c8a4e46767f4d707d448afd5068494cf6334ab190692716ce863168707f3c0c1db0027a57d100f348fad9f3519bb6a82d6e6633ccd2d44716d2950d2d5cbc89836216e52e9f0df1b2f2307043f082e38636e3c8c77cebf782169b44092a98488b0971465344a4a72a107ecd7b93718fea92938ca4510baff33c6fbb5242cc1dcce58d6d81eee0904fdb51df2eb05685580c6bc8a6321e51213238b85a9cde98b191f04a7a462817a49297e08266199e18d45886fa58699c86f152c1fe8a1615dd1aa29c129dc882316ea4adf63df567c9af7f01f2f1b3be61892d4befd564a0d03cc81bbc39bbc518380dca488a20072a14c06bff7f1d86b41d3d98cfc8a981b0508106229489e00f95e5314a0016f2a3fabb862a612dd704d89b89eb91225bac4441d8d81fed40eb0353e5d642cb7e8924743385a427bc0332208493cde558ff72adcf44d585171204a5ebd8b82291adc0109354e351c0d6938868e6092e205fb10b3660d0648c926b8f47fff486cf10e667d1142a30ff4cbc4e8e7fa5a912830bc1948103a01611032843059b47cb0e04aa7525d0eade983375847eb36fa84f9f6a1d215113a059afbc578261a8cd0f751858065ca72443fa3be6011cdce0a0399d1c280861c7100e02764d2eb902037834bb939f856476332e0d66e6ff12c607c7a58947ec6e1d04443734856e03985294f1c4ffecca0d3ab9124e111963cee9452d12312d1f60d70755ae00822b9c6e9ef0503b1c10d37d3033c9ef67b5fa10a17ce5cfafeda74fe5321cbf8c7b69b597689a58c8c5f43636c682e48870fc6124e525dc82f8fe20aa827520bff1f137b8bec7ed17b149a10ffba9f90858ddc52dcd4f8e9365119fd3396e9942f5f4a838a7b67c66360df00b8db0e81832d2284011dac8837c5351312a2ed50e360543ee646beb4448eb7b1ff2becc767eb7dd498fcfd1f52b8a8ea24bde99c3421646b5ced19a706a6b9b96dc7df7bb54c08a2de5f0fe0a9a5b8f56bde3d8d2a750220941e3164ee73f2800bbd2dbf0f56a30fa5590f08e6ca1564e4bf37c615e6f03b44d6de4728e91f52953018d05e1a8924720d1b4bbe3c618d743a9560608ba9c286ca53f874ed46691db5af2dd5379e0019dff111003d65afed41b04abb5fe9c0205b016a5a3f4708c31a09230212823f8d6cf176def298c1c94f9f0125232d33e3c84366d049da31ce356cc5a488b44f8f48bc6f48f0251a63444c538e23923608c48ae8b7b5c5127b945012ba82ffff3f02873ca5be48e13c6a144e9c9f3abdd5df60fc66c09e069b57757e47ed1b9ec3a9b3e988d9e02bf58eb886fec2ffc9833961a42bda58fd841f278ca05a3784e879237e0e6b9aa02704f8087abf48288e4fb1bec129a85f3d5614ae0657204cda076f217cf74a0a63f75ed7cd57d659d96f086aa198d244b0f58b952adc3a82058e248f6861a64a82745545b8fda98689ae7f75b226c7ad950060b3ecaa7c79a9a1b6ceb72935320ec6fc57445780b0dabd2f9ee7100513d5b42d3ad4e83cdb6d3194984aef9921e4338d31ba212d387d68fc8902a7abf5cb3e06a21bd62872e6609f813d0d7ee6422378b116c6278ada452ec6d52823025d40f77d1ea6765d3fab536bd331aa819b75453df5121643a5f12d0a76f44ed746f57f5e966b2c097c836c971bf808a6841c6c49d88356d341f8b1cf8dee02dcb4ece4a81c5fa1a9411e59c76c9027da29711197317833cdd22096ff196c07184381a4c1a2ca6f1ebf393dcadd8ccd62baaa55633c43f6d195c8b5d9d6595150244e9dba15829ef4754f79af4ca99264b75f9bc09ee31377f5b1d51fb6ee5c25f3da829f3de4702c7ac9ecf6967ee7dbca78c5269e323f467fcc539067deda6c44d5a168ca6c35cc611112c4bdf229dc148ca469f21b4dfc1017b6e50133cb8bf697b0a3bf39eb291057da8ebf685380bbc2561a8b57084d3cc06fbd7a35530974c0aac5d09545378781f482eda9d10249ded5c48c053f6b9da9502fa32f6dfdc1fdfa1d67e18613cac8652e84b4002ea632885908c1778e0b7cdf8e50c99eb909818ea8f9f61e1823f074608d8fe7e571a193a8e658cf09cd55a0058f11285546f6620b1b7fef65bfb61692cced4fca18862c516205e058101f9d7f48e9cb3bb2acabf550162183e30494515a8785a379691da8b5b0ec302fc67bc7629f0e0b9ef75a61b015713389916c82161c8c22ce6740ca2d519bc138545cad87a2243cc5fe10a02ffcdb1203af95e544bc68e6c0d1f89e526ff4da10ca14f447cfa759c51942d3ec3cde28506786a8fd2cb48912b27add4be2cbe0fcd445e42a52953eb1f5f8faa1aab76d8755bcb71effd1b784ad3ef60a62aeaf3882de59c98a28ba902029859e6248e4dff8b5e178c73a36d7160f2cf4870063c543775501df895fadad783e177cb10693bd4dccfee8e5258b07edd19bfbc21e2bf298436ec0e47240179166864710f11347a6d9dec36a56f0f535451d7f25bd1bee9566070d6ef151b964520b82c487c6440a54c2ed0e0e16b0b32e6c45e08a948000fdd8b6cd73cbd45ece49b3f558afd904b8d0ebb201e01a22e9ed0594eb1d5ac4aed6111034ef24b8eaecef94c98d94b00087be982b8d8d0b1557de3bab27b17e94f41e7435a90a55d7cf1082ced8069456446fde8925217ffdda59e16b9021c076243ecfa857d309bc404eca579d06d4828783817e9908170aaf2a6fd00e5cac3c6807824208f7f3057a599af05798370a81c8c98c052948baf095e8f4c792798e61981064d668806ea5bbcc72dc6a8329a0eee832ddc9929a08af1fa94c64502a73a4cd3a83dd0264149861ba44b91d1c3aab82a5f55fc66331f2fdc9ac14dfb2398f822775462ffa92dc509cb2720cf2bb9646cac715a160f473a6d5732de579edd2f557d1e8eb46a30ba469669c512318f550bde4e6e1090665b446475a14e7f3079a36bcab36b05b254435ba3877ecb91fe87e19b26ae0d4808bae174a86a4b5fdf9e6165d0c5f741c66187a98c3d0e1e77c2031748969eda388f63d8ccbf1aeb41234757d2607e7972d7a695efb7c1dce0647ab2bdba217c70b37832c49ef5d1227693587e11d282efa7b9811eebdf01a2ad871d1678e7a47be454f06d2fbe39e7533effc173ef496770388388afdfee7fd128aef295a988641af8c59b0eeb6095f289e0b8fcaf7b5af6318457eee5e542664fb7b24140b5d0b2ab6bfe9c2dc26524d16474bc784fa46feabf244d20bd4853dcc17b17429a6ff65ee9d1bae7fe7bf17fe07fb1670b31db5c9c9a82468a67f455a01e744fd181f30cc8d77385057b5c58b38289ede3f048475dddbb038e6b2d527d91955bb948ad5dda9aa80e5374e8685f13f3d18ea62e0caa0edf38052d461ac5de90cbdae28d7178eef8e0ae897129f6ad4d3b47ca8de0f05076238184df2be7e223efae12b1f918bd7ea7e2920d5420676b64cd3aa960fcb3edb48c9a999110befa3eb9907b2a1d22b85f40d28e36e96364e7b97f7e30a93c4d1979de460f8735d0e7329bf83794e1dd9ca5585e93384c5e6dc638dd46356435b8bd2a00b6be1164dffdeb3e987222fd9391b99f4734ee6e7b7d1f8adba94ec506e651cbd4b2443097e6ce98095397793468715682119befbe37151d80fb6fb90078cdba41665e4e0072174983f1e1d19ce38c7271a81853a3eebc949d275cd2d66b0164080ccc2d9f5c2f21c2f41983bb167bbf2081295072c5c942a8709ad111dadac0e6e6cc812302d473aa1c83963d6b79ada248e7658ff9b0fcc276bf3c9e1c9d6acd03c67f9328e1b302b65ea08fa5baa04ed9f925d939b441b091cdd4277933bf6ba324cf5438bf6e8e24c5852235be67e25aa1ea56b1d88b371baa9138e8b8518ec88c84f34803f3b3cabb684c9ed361393260f0838b13e2ebb3e48f2b0e4a25bcd3a57459945755819402028decf4fdf1ad656607a018e5f70d7e347594f9ab87adc1bd7c0b2ba23f86b81a24341399dea54198d033079f6af5abae5a1cc99a4989bee23dfe1fca2110525c73cab76f3a2987f186b50b1f4858ab9c1214eea05e3260957d14e02b00cf54b24cc4d5577978541659ee78cd921422dce54c4a48a8e952cc18b97ac9086ef82efe711efeff2c70bc88ed7094f52861bc4e3c62bfd628268a3a3e016503200532619f541bd7badb6b9d036f8c7e6163579c7e7d7c33ecc6ff4dfa809da4eed604dc95c98de6b02b9b171369402dcf2937217788a8b199a6f774eb58e5a5c17d6778c23f0334ecebe2a9a1b1662f0ba8abbdf77e1e93825fc3c644e8e9ef292b28bda42f8b8e82986f3866d2f2e8c542b8c93dc2355ba6e1d42d051fbf2b5a3b49e0b0c94da42c7bbebb58774693b68e2627b7e37fe5c734424610ac42e7662c9f03cac2e6965060dde9d959c25274cb9b9a10ebbb2dd7d496153da040f294f2c3f82a7cb34ec1df0e24e6c96b7ebb55d742a40a8a3af476f215e9a5e701f1edc7dcf5c50c1dd69a0a68f84a55093d9ee33eb926169044b3b1aaf2e79ec7edce9a95c91a975a31c1db1afd6238598ce7c77c61b999f46e47eba770f913650122cde793188169674693c6db6994e40c5157cd37fd2cae4ccb5a10d3b369a75ec27b9f763241697542990ccd4b9f65242824839363c99686f7a8c8278c968f6e70d5eb4dd53dd1bbf5690c25730795dfffdd323bdd1a37aa8473dd453bdd20bbdd543f4ce8df9bde81baffc8a1c8c7fb38d68165da16cb4dfc7f47da980b6210d4b055cdc646e8e24937e1395bbe52772b28db31643286970a575c424850964115c581d0c34f23595d64a2752fb234a53e5766956c0dea5e63439b682518fb6ce54f8c80390477929f79dbc1473cdc385d9afb94a3d1bf50aad346e9ca643d2abd42fa3d007f5420d6d5936ca2978bda5fedceaa23658a6c8dc7ec67546d1425c5950fca57fd7b7525f57f5bae671b385998b6ae89b898265574a2ed2b27565ca76554f53a70ca1778c1dea1361c6f4b3e08070109ff710f1c7add9dadae4cbb2a978a531bebee5076a0cc6c7ac919f648fa6b97a9df371754c988c4990394f1a0eae11fd7cebe84e63ddc312624c3760d341e0a09bb21288d5aa08d844d12f8d74a3d47fc0984e6fed91d2923fcab9d67142ba08bda3b041158d251de25327ccbe918429510c7f358088a2aa5094e5d58db3e65e89f038166982fe8d21f62ebbb594e1c3260dcf5cf11f9c88fd5662d17a5d494da4c846156b5f61557e713d0cb4738c25d8a78d4b37e62bd77aa963ddcbca778c2e4ccb840a45bcc275dc1b36c1e82a182747eec233b73a617feec225af304aa170230891e4259a512cfb8fb46f081b48883f17cb68a2c3f911d1e62cfb217fd6d5d5bed21d21c5e2d146798022ca5d6337dec7884bb88db12a1a982f030c24933758f4ade9388e0eeb778b553a81c8f4e9e10ccfd3707aec654cda17cad05cdae33998540cb33a5b26f9e8dc8a54c16a8254df4300ba87bd6816ec06042dc79a9731ed3cd222c539b83d86aae0f62d48ade47a214a1658722a18354fec5fdd096087952361d11f3cd83d7df7ea3580c3eaf1e0aba8fe73a8833a232c385756a3d94d5c478188aec13a6ecf52cf237aa4a6e7671e43c9ddf490575c8613bad0c4d2ae086f3fb268cc00293c96bce12d63f5bf212849f562c8ef460524cb1f055cf911c92a59ad0d25caf6075dcb1389f6550e174d88755f8094f74678af1d7445eae78f4d950b8e1be468098c8d4c9918d42188727c39e69504b422f75a206427a087c3fa3701b00c8747d41d6606b1648c89b894e22f179a0206d029a46b61248b9b72e1db2732f5fa45344cce38dc4626ab0bef20195d4c8aea593cb9cc55483c582407a835f1c0e1c37166a457103d3eeb48a16485d45648fe52a4e7178f9eb7299c2d76425020fae39ee99e2241a2dd32b319bc1efe617333305bd019a004392d8ca46ffaaac71d6308fdf868e5083f84d6a357f5566ff5548fead5cd402ffda4777a57eff4ae977aab577aa1a7f4365a104cdcc451269ce51be5feaeb55b6364c5ccaecfc2721d63a4aff372cde5f1e655ba94197edcc25ede5e6f724d12c3ef42f63a3a052797fab86ff65995dbbec420e977cea55f6ea75d46293e9d2bc23445ec97962c1517c49f8262a5c42d3793e8b4b710ec74aa11a0f2e75f224ad2fef27fabd7da4cdc3a0f5ddaa4cc8d4c720bcad9a0938b5b227c8a832b6f84f68909e53dfad02d96427fd85bb7a465c050b83047eca3ac5829178048bb18ce8e0ad23a7d62f24bbbc90db97e7c0fc7940b30cf48fbbc2c6a2dbf0eebaf5ee796726e7db8fe8df7cf475bbb2fa2d2c7dfee99391cf9306318ad413e62ba7d60ba1b692d7a6fdbce66e0eec2cf8d44b06364e869988f3433331f33d558e68588b8fdab179df6d6c38bc94b61ed9be9afa565b619b6c7762b769b33ed5d84b0075276caecc118653c3fa52ac15fdd80a3962b07ea18a3a5ffce6a630b3475e632de02be6febf11bca9f8f8adb711b43f3454788d8271bc5c5f5c8bd56bedc01f17e536ce954d7c284fb6c3b2b31680511f3f2d6b25d564f17347f4fdf943052cea079e5de03fab753bdcde24f41e3b5c3a7cfd39335e7a1c92017574f9a362fdce69d8733ad8d134384ff65b628e2de7d542e5e14379cef7ca0b499c360ea27f9dd0ba051d48b5d3c7dc9e48b31f3529cfc4ce104562bbc6662c4bbfb1a9a10708b63563e8ad6966605aea6b3904572028c1346d86e50733ce255b6355d1027072b1506007715a974e1e4d3d8d550d9ea6cacaccb92d74fd20f892ab88ac6ee4d0113027d81894e8fff9c28661de1193e4471baeef300255939dfae980c0513f9723b2cd2bc3c99c3b9b5c89f23a09b562b5c9e8e05ac6631464d90f9bbcd9e419a9047b7e48786723264992b817faa5fbebb34d5c19a5ef86492204db8dcfcfb7e8b51a4894874620a36b0147c9e0e60494c31ee3308dc1f5c6b1962680015422882c114c35ddb852e90df1ef9967c285b417528527aedca440572f7597b18344b7376139ed94f75e310b132490579920a427a48eda01d4a74a05f7b48c4a158b5b41c7c749ed9b739ee32d988b23c373ff98ff074440b27c657795cafe7c0eeaeb7371b9aacd2053d1c1168720da49e79e60538aa955c4f11392adca07929d8c9f676e06b5e8124e098820cd3cc21f8ea9a8ab1e73588894a80773142d2cb70da816ca64b6a49bf3f9aafb443c0ef8f52522902a373033733df992406d1e83afbeaa262b68de6c2416c2ceef3cac4e81c3f8ff52bcfc22ad209dd47569166858e55fd83b3a549224a0c2f7d6c6ccf5336f335acb15e2087499375747c33aae134a167635db3120cb6c7f570dc462479f75ca183ab8564ddff9a7354a1d18bbc7d94dad691ad3fc1698c4d2dca8f17a01b804a698dfb5e8d3125c9b98e3d4d3f32c0fcac5700b0e97c5195d06443132ebd2d77e58ef774d8e3777e39d1e3d7edf364e1da102c5ad24f84490eebc7c45fefed25ab1e9854f202b91b8bf0d2c52a2c04fc15c8414a47431f885550d2c1c12fe460753058786ac1f2908a6240c4b2ba1d1842b5c230ab7f2d3ff730c6f5416a7715326a4ae41c673daa757e7fca1ee41652a8d12d496193e175002a529fe0684e43a943de20ac081f5cf34437e3b22d19dd2b13017ac328198e61c577d9a70178e6865237d40d0bcb0d9cca59527c81ba718ab1a498e91b69ddc36238ee6094fa4a4e74b95b696de650bcaf7bd033e36eafebfceceb1eddf4b289af9b96980f2d5b56e44c2ba437e188a53c1d1e3eb1a119e423b2d5e38b83ffc9e9b597111212839b157e5698d8ce71b209ffd84e1eab55b6d8a3d9ba1899cb2d377c01a691d914b82dbc89fd9651e5c7b1db2379379ad72f3284fe4044ff5c8ef737e23503f48cfcb2edfea9aa34c24587529b4c8eb8893012bbeaa48825bf58148e5e688fad97371e9ff95a923201b0cd4f599ff44bff5d750ef3dcd0e2062487af9921850d09d8914aa298781dce1b68570903ce123a1860ea8aa09a3748f74e3ab985c8b233b818bcbcd9def7db71c5f97bc597c3ecad50baa5ceed8d3870d73282f660f6afeb6036b8f081ed6c320dfbe63b8eab0b469435b709f17027e051e2e01fd1f26e58b66e38d6ec93fc97848bd11988e854ade0fc3ac2649b5a287180a05c5f71c42ebab758a183da2fa2057c754a9cb41bcee5ec3d0fdef8f14e8d1cbf41a0ee95daea1449c8f6890e3fa320c28571229f459619ab5378c08047e2da467f74a894be86747f56f035c49255922fa7a8d9067b6cd4336c88d96343c5258c6a0002ce722091305ab22b87cce2d6d066ebd36fc917871a72adce27e23891b2af41b31e329710fe6a0b28241582c209b624289274a697431b91552d3a38ed6b69eeb4c5f54574c8c46d745574ecd2a88db2ea5cc3962535f5a276ba3e3f6ed8417805c8f49ded74b5b2ca3992e2434806884bb9269490fc0043f2060f6d49304b7e867a8c2f2aea976db1fd8a2b31f61040df80a1289e919bef8d7b6abb1eb08bb2c73bb88074f017c8821f1da35831d50db36127a289880cfcbaaf7e4ff6c6c9314ff67d577897033d9f39e04b738ed988cd16e48dd72b8cb88e5ecc8b2c75bd5cede8049284deba965f59c14849a85e9c76e8e0a5732ab9e509eadb3bfd9a3acf3239d90c7ba0f5d0e3313de6d4d48429fee0794c6e8f764bc5452718f4adee26ffa81431f6a04ce9422d85d39a67b4a1409c3843d9a6429c73542d228322a752fac117f0656e767dcab38dc9124560766261a8b1d2288d3a56964b63bf42ca45d1d3fa1ad604f48fe5a0bc68bb5ef88cca933837c54a053575e063c337db261d8fab76fa36e8d47f6d45c8b30b7f198cebe74539ee520211ec1afdf47839c0f68514079de8e7ebe513db434bb8dde30947d35a6e7ba37c70e4840d40641b935a4e9bcd93a634f2018888d5f745561f6e1778ab6587c476b71bb40232322d2d98018c4ffcb0e024aee4ed579d57f416e930824ce44eadbe3054bda2a0d580a7dc88bfd88d2b3de2f7ad4bf9b8e904cf3cc20f6918ccc0b13f94981ac699bc6b5991eb1f31dbef86edd86e1f32541e8478ad5b71985395b42051450e1a073e83163e5638214ac2fda496eca377d6a1d132a3b86a32108c411c2909f5918dc3bc58896df6d87c94eee38c52b4a7241043e3882cf0d8abf72c88670b4d3dab74b4218142252c45a519992410de76e9e7e466e041eaf7a550c54a57dd0a73b3200240f8369e2e3a8d65a8b524ba604442000da7c7f595e2d7937e67c130937e748347c2e51b3b0ed2e3fdb8cfc4172a1999f0e22e48e652739b0db521ddd87ec54d77976ff0d92ac3899f561bc0f6d388e88d03246d9c346d20a036d069254429366ca6216a5b1dcc3ae5cd552f03abf756362532a27615dd6622f2f42f222f0d5ef273553c1371526b421828b4494c5bbc40a1c14ced3c677433721df983f45622145a0c8bc34839547c10ada2b8018ea05ddfbe71414c76422bec38e7ad7b624dc0b017227d82914f34ee138b7942e33ec1884f18e989c4fa24639f604c796280c5c5ad32b008dd74204e90b1b2bb40f43ead71fe1cad95561490247c9c9ea084d37ceb4ded5591e004431fb07cae871b3d4f268dfaec2aca3e2e6f7564822232288580ee77707e57d94c55ec2704b502ad2fb95dc1467020ac5e5c7b74e9c5a456b95f75ba1e3ef93ff10bd6fade1013e63215482a2d80beeb9e3b3251853734886a8f2cebc1da92e51f3da6b9884378127cd06c94ee67b01b11b7c4784c88cd5f3f7b97b2c4ccb40df92414863bbe43965573ee5a87bf9ef0d3e94459326216756d4026c47978a33a25b5688fc358741ce92dba338ae313e1c4c75dd6db5c70e6fe41b75a86d03601a9236edd44de29f6d87d289a714452821161402d36b48931d8a246e935e8b817813c7acb1933cfa19140f5410f8af443e4f877c168505b88e1f73a4745a5cb835bc18cf9a5a70c417c7ee89a18873cfba8ebe4c4d62c4a36b0244a4ae1827fc353194d8c112c27018bab8973425be6500a67c23fa909e91b0a09d095bf4ccf7f947e80087f4973f32c8c66080f5f34c3f84c2325f8aea09541a062c0a192545bfc86deac27c1ef50150b6566386f074b62ae4824da91e438c0c244b176bab5d53e2a8bcb2df9a70fb8361f42fdd672ea1e244c96a006d7928fe3696f7eb3b2e1085b49ce027d38a09c0d19a5c8f685c1e2c1e2d527df4d79f716ce7c9bff2e02607dddab7958364b5309585b8dd2ab662ff434afb19b6d004d6abe6add00bc3fe2078051cca2a6b759474e370f14b0b9761aa836494eabb44410a582b4014410518fac4e0c3417d360f38714ff6f9f650d62ef09815cdd49f5d93de4ddf12d7ffb7e235b538b696c63922a356a15a5f62aea6ce13910bb856c1d8be860f5fe4b92148216d205e579059eea84e9ad9455751ab88eff49af79d9f11a299bb1c5f532c7071779bd841a7968a38af32d2889a9a29e2edf4aa93fb6ba34102d934c1e074f774a768f70fa0d8921ec6efe9451f80eb99618248b32856870b51fdeafcc310162a775e0a8a114d5348036a9aadd8ab32669ec420d58869a78b55b47578b5bf9acff5ebdad5b69ce89607c9c9e39e5b43846636eac0fbd60a108d4ef593a0222dfa91fe39c48911c2038504d3f4539ebd04cae0849799488e7f00f37d7b2af42f105e086b36290263e48b43e4b40c86f2be5e5ddd06671a6941ce787c3ddd0e54a872bcfc00983f8108d32d048d0994f5c9e80cae2d2ac650dd0fe39c017a8d78803f4c163392e636ac2fe50e0e9ca5c6ae2acad12ad61b6c99437514c99807b34c715a324bb899811f1800ab5d39921597be8188e5bc845e680223ac35e1fd5e36e951d86af4d7738befc2534abc41eddb7ca5aac567d059c9281c2850e22ff091d0db7e8a39e0cae3c762961e509d4565af9b961d9a38df8c2777d5a459238ab77ac7a78d62be00fe6d839968ad2e2fe66aff3b296aa4c6a9a51699841098ec395279609328ac68086eaaa809af5b8e7e0c03aa4fdf2721a81c5cc1da420ae3c0d82f6f90df28db08948fb3b7fa3365597b9336930d272cd8a322e816a3604bb3388c50ff13bf10be95a8f7aa6f939b382c43e5ed4a84bcd5c6785800bbfb04ba148d9eb86030816bfe2881d7222364550bbe96bac64a01d8f83b07a8ccd3cbddcef0c9c77338d12063b8623a95c2d52af363ea93040047039726c4d3f2b7fde0f5c0a3a8308ec1e915f8c9c99f940e0950341d4104c423cdb0bdcba3095f8d55319dc236ff13426a861e53e2c6c4a400061ff07e4fe531ab229e8342a3b8e624fd0e14bb4302755f588d735c3cd89fa4e33e7cec55a6eed539482152ce9110fbaafd0d3184852e2fbb379d298ca369759152adb6a10ff4f12ddd396269c8787cdde441c35a7949267467b625764019f0449c19d52ba1bb79288328819ed7522d3578a8ef0492fa61199d1d6160d9b0cc39fdb4e0da7850f4baba985de484a05957cf234b91679196d1db50f9aa57f3f9cb66438c2bab9d0bbcb68730b0ad304b7a308361fc096d12ec9fe6ed8c19826f4e8dc7502276cc91189cd24e476dfbd33302464325f7bf3b117c3956f7886d1a365a853208e9a5a1ea7b4c885e505df57a13a24962d0f1c86cfb7deb01bedffc191e67234601f5972e165450a260745b415d0596a09081b391f1f34b2f1a18bfee9c87b78da60f88b0d513de3af8ce073e90180e09ba8a0a01486fbd4b02de020f0768bdac17a06bf1e442368c12bde7f78657f65a20343a2fb7e7db5050ca1c6c7fd4147d4af8608b1af0025fe02400e07a0b80a0107d6b6508629ce715c595c1c58d90debb020d9a43dea87b4fe2022ee9b18db2115b95e05a0ab32d38cef391bcf9ebe5252f3170e743582502056347893d44525a80cfd6b987870a8e14cc2c324b0e87688962751cbd2c15e35b08545dba18b2eb529211f7b7659bba8749b77b32deca8e505976922fc18cebdfdab2ffdbade0862850e90953296530c61800afae7c297e594fc3d91935901b9a6aa55a9bad8a591297e0e7ca1294f8b684ba0d6c38d2944c4b9fc56223257fbd87909f5d130f4eb1808c87b525154904cf0e0960707b17d5e75aa1d3ee77bf8f15e07db15c5a1b6ae31e0db4f0aa2382a1475588dd2053293ee6336a102d56cce38cb40c20b9c98aeae6031f20dd7861b7a25fc8b844d8b29209e4e353a5a00105097274f856ba9d621122f210e878a44471f6634c47d78bc7fa971e3542b83f92e6668da79d003cf3ce6007e686e072e982a7c1e60ab6662fe5212a0ccdd9ae26bb7e6602e08abd1f4d9b1527d11a89cd8cf3a1234fc3245fa21e7d4b3e7a21c23afd0b5b721303276f4fc03d0932481974722822e443bb41656d2af05ac0be8246fb1524134f13eb696523b0853d2878086c3cd7e282eaa069e80032fb3df7aaab6ab9d932b7a13bb05b020a7b184c6493e6450691a4c9df2553228b0ce3fa9c5c15fae0224c1092c792f78bd3783b41216d2dca8059adc64da757246d853b18ff00350459f5a700a707a1c28009f90c2e1b4bb4df7fdcc472ea3cd0e916ac88bfecccfe34bbda5b7419b1eeeff94bb99f146a6019f8323bfd9661a17259215eb2977ac5dbd7e768c273f37ee0460a0667a35f010468810e3177feef38a7e954303b3ea9fc4f621543601ba88cd684a374ddcfe0546ce2c0425003e2bdb3d163b0e7bb3fdf3e8655765731b35e3ce2ba8acfd2123843d453bf2396a53a8cd2a39562e3803d2a163d8d30b001e890b9ee1979b06527602c1b3c0e14bc095958322be37980ab8d3d71ea9fe56f240c001fbd5da9e7db96a2d610531803fdd0ef361afcbbc45d02eb3988501fd586609a39e80f02816ef9c0f222e576ae6b77ca15e89ae9151067f7c25877cce84f0b61809507216dd8ee326ef7c330bb38d53422242d58c82f58cfd8baf1b08d73a3367caedf3f51e43b4adcfdcaadb4b1562208c57c89a8eb20b65fb00d55e54b500c28f2c92e54b366364863e3e3e3700b42d8c161281594c78e76c0878d3c0c974e278625173613e0681dd1179cba065eba90e58673e6057ee9b0228400bf3f5b1f626dc01bbea8278fd01bb7be4e7f509250e99c852c13748d7dc9698289c9c9025fce250663a81b3866891501b825d0f4091537c96460fddf7b87aeb9abab9da9123b93a0b61c5200fa2208e30ba5fd309cc5a45fddf7691f604c5b15281e8fa0aa5a01698dcad6498523bf7e01c360638c0c579ca8827b016eab597b6f3d7e10469aa9181adcb33761b3c8e0551e6516c2508959eb1ab9ea8f3cfd8ddf00f9b0718fa752680452ac0c85e8ee9b5eb0331b9f7af10c97d1a519f7f9dc722d6a1ba05d07d89b1018f2b2f59cac83167ae683df5e02cc7ee74832eba57d5d2a3f6542d8cdd9187542b15f7782004e0aee0ad99776eb9046e001acb30983e0852bfe0eea8d8715972118875d983288a62805b3c5d3e24ec8d6f71e943fa779f8b32cc38a5b28bb8cfbe34ad8e0cb0a4cc74e2a1506640e02377be58b8cef50ba7bb05552abb934a3c41637875237b7f0dbcde60963fefb50529f4f41ef326121015dac97000ec5cbc1223cd187c7846b60ec10b2905e7043d3a8131e30f23856f0b38f6574826dc2321be86565531b5eaa55d5403e4cdaeb2e41a18e4eae73896bde9fccc4e6b34f4ad0a721f01aa38b09504c1b457d3c4adf17c4bb44b0175d3970082f61f39bd8786f909b25632be48d50e99ba7cc0d69aceee0572667e48785513c8e8af7f58a934cfe1ca0e96272c3f17d2a7a1d4eea48f86488fb4bacff1e49108ec166077e099b5c4ef6295f724d800cbc016059e7eae87ad2c5c82a9b646db39dc7ece7e8dd8071bda625f50aa4320fff46594f21eea73e1ddec3a7ff54a162a22d0905c9891275cc67d435d7cb148d0d01770141d950c9c2c93aa9c7919e34d9bfa56a581202faaec97237bc4edeb86f405cd9230e11c829bda395355fc1a700cb61fe6221ca9866c6557f6769e29ae4b08df0e15cade25507277b6a25138a12febe74938181ac941009ea14ee441463397e0001dd90813e46edbf911a6dd2b9fd2cc1e266ece489b94c84617e720653589b8dc0ac150b82cd2f865b99d2e104e6f8cf9807e6133b278e7d7cfcb1e494682385b89b855fdc63b24944de092dffe4e2bd910020d3e9a690e6daca6bcc33420178f14b4c38b7c71e477133ca1624e788f21853e11a7886f37896aa0d369764a2cf03efbce0435c79c73e313ac9283b34964aac5ad411727f8f2566c7278ae631bbed68fb6b640d6678dc778fc1eb57437d43ec67700a37bfc507c4670d1ebfef7d293c1868a0aa46742ec5f60815cb9432803e42080f2a3ab2861b8de87118ea22d63af4ff256bcbd8c996d135c3a5716e8d4236923113f5a964bb7c5013771e2185c893898a9f112ce1460dfa12ba74bbda191c7194f33b72e5d5ee78246c3b1227dd5db0ce0b4fbcb214ae1be2c5f8dc640d094681c594a603fec8e867c8f4cb7428e7aff290080e142754f62047359bc407eca5e1d2dc090a2b1d0829a62bab70550c9099168749bee53f1a1ec8c83de61f4abfc7834236f1dc8357503a59a9fe7c69f6091676b7babbbfe0fab957ae7ed9ced0a537f77fcd3831ca297f23e1fded1fa7acfb5ca40af41c1eef721c7acb4228591f8a4e69b49a97986a8ad05a385a22f4ffe182eed8793707a36c08f67b815883d58cae03ae3580b54fcf55104be8e2cb172176203e7626797d5f8ae1e9014afd601844b1f46bec270ddd4442ed737db8b01b555c188fcfdf74ccb1e317ae9a637f89caafb358369588a2804b2bbf5f564091de996bbde2504cbd6a123992cdca366232f1985849c97042021380be7090471f5935da4fd8f59fc8edb0394c368b47d0b692c0a46311ee4ca8e8977b17e9d937deed75cd3db0b2008e0703a7cf8215c22cae9a31277ab5141117809320496df445a25af731839ba89f9dc423004744b0a22b6ce8860bda83740cd2a0d37931f620a6ea8ff694a5126e4e77218200733fb7addbd03909d74a429be65b71edb99639d92f08b940934fd9ca58579736809070b5638b317f9dccd5c8ec1056e99e7c04b5e58d6f3ce82244a33fc4ed10098cda0779127e3049da951389665578768ce64f6ae86c89046cee2e820326b0a44d8daeb07573990dbd02112d88094a955fc44ff98b459fbbb75730607b750831c41ef3d9cdd5e19153e356919ae0fe27497674e481cc05873b254a83a08d0ed747d7f88f534e2c78da2902a04bd9fb486b427af6c6c0bb1b26892024a7d28b75622f9b287a973c6e8bb781cd2d5ddf572811bda8080d60dbbf098e8b52c97f1a86c63706a858058b00f80f90b86039cedcfa854d83112a3a1430598011417d465b31e62ec64ee0d2802e01abccc2debf9a6c4bb2e909bee4557dad7685931869002143c2a9c128308926d60110ef95a4df6037178739130ef19de80d75ee82d2a471077e0bd399be5a3508b35666a763bd38387a440f47898a1996980c7267f71a703695127cd17682257c456f4780948d6f54c3d9139a02d906d68658cb257ca8c720576a0096eebaa582159b7d0c7833f5becb6d5e891a18d6151afa8b7fee30f044992849bb4488eff2931d10427c8f29bf2a855e8881e7b50030502290ad6437d10c1d9249222b408d634e81582716b3f3b2554ed14f7963602d368f7909905fe81a61eaf8f2a6d42a1677eade5bbb1fb77e40895374f50fd561c7ce5307b985f55e1adaf652a74a3f67e1b9089a26fbe1158dca1e304206b94261016cd1fad1dac7f6a3a7b28e231c1e9203acdeaec7d59b18bd217de9e03a53d7e5e4eb33dd0624d2c0843a2a070740db34adbd4066a923354b54ad095091b0a730b53f4ff3668b2cc289c709747cd0a66d6c1de60412588f320cf0b27b80a4c855a01f1ac1098a72d9d0c3d1bd76149900820a1a83a99d98988909d01b621a0788211ddffb34bd0b356beeb1d3af2254fdb807e703e1fe0117191b218e1cd3aa3405c44c83c010d7b6e6e54e302459fe8970b22560471c1a7bf6c4d08d79ef3207ee563a3bd85201928d1590062419c6d77176db8a83c05cd8f717a3cb378870c2778e244e2f487cc9246190ee26e82ea00e7397a7460e93b529c9b3856451e573dcf3f6b914ebe8ed5233ee229024350414e9af8f7343be346f4d602daea00bd4040bd3bd0a246d4d31630d2045bd652a59b92b5ed9b6aabf9a6268a6da1004459d506974e9f25f11aa6e2f4b4d3c0cf464b1e19f4657a5ad421b23d4181f7bebaa453481bd7073028e73bce441a8c74646dce51b5d33a9423e9bbcb8361ed8ea5425f59bcd267bd1ee5adb48d9c52bdfe8d39728d556dfcaf7a8e9b8020714fd415c33927a0f4d1e7ad8b8151f727c495c650dafd87e7f59778278650ee5c45cbed41c757c11877409aecf8778115470c3834ee5266f38152f1e55768eba37145ef148f8554144521b86cef638909994cd295fc3b368b4fc9fbb48c9bccca3f4f61a5c127de2d537d6357249ab0997c46fbe7de3f21523cbe4b012d02769888e7148d0f2427ed153ed0d044cc8141bf34c305a47de3da14794058b52bc9fd19805dd981e7ce0907db8c644abe718a35678caf31d6621e0863d333c53d07b3e66c6a2098cfc026297ff2704d538c459f3a3626f35fa08a15f7f20917c45f47bbc427abd8757a050bd1770ab725ff9b548c2d6e580812c3b3f47443d53b7fd5053f09ad323d1d9255e98cc8fe8d3ab4e57824728e13c32f4f0715ce4b71c351cabc3c1d5498912369b86064c265b06ae58e27a2049b7197a72ae7db90624c956893395c600e12afd8f0fea9d0f3fd516154a7c9b518706b0a5d4b2a3e2349b6bcf7e4c0e48a4b0c08e45bc6d6b8490d0577641b8c263d53079b0d1c17c05c4b255c188e5a2d02f6911c79d275268b8845c5bdad28f0c68f9e693ebfa0070778aba3e8c74b86a60c655fcb00548fa67dba8edb9fee9cee265431c5f0343fec49edc63e369f21a353b47632f4e72910aa89fb0afce840dcde14a5421fb50e026b1dd4f9704836d57e1bebf4db5ec87a8a15b0887ad14af221e8d2f4055d5ac467b83d99f0644d6466dc91160b7acd990d35f39dd38c1c52509863fe0630a44ce08706b5002ae8db28d0a1afe61b0eaf194479fc1daeb69c9ee371ecd809abd452c8aa1b59d8f3c840cdd8e6a0139657887912ca022839355a75d7a785bd99024cc5942d95633009695817bd3ca8148c02a7e741c6374005039cc43e6c526d9c5b913cf00bbcb05806703258162e56215efdb519b70204cdb197e80ba60ff01082f2569598a270e5345169eb8ed28b5526a8ad215507a6c75118ed9dbdb50719406477fbd8aa7e6940e08abc002d7867f0dcb3670d325e12f699b325792a103e40588086b577fdd3612e42f4c5ad0a472cbc3b00ec55f0490ec357f5508c17876fe12107592b43c5154c75ffb224f110b26bbdb1783ffe952c8763343d4d1fd2927b437e1db7de3fc064a35761f4117d3d1273030b015a7dc06c1feadee5268ea3acb534c550d6aa4bf14bb75b9816192c91ea6816c033f70fc0d8aedf849c44bb7b2db591b23fa96ba3ec04f9b7245afa03da880f1ac50351a6992d60f6a86221ee0341f8688185e011bcf791cdf0f67e107c7e1841ea02b952d59979c0ec760865c3206d81a5adbf5230e41610ec6f440b37d601c9f22c3907d315939ff011e72b8e1b36b7bea57ca924821aaf82f38a67c04e7f7a0960e9668f64264ad42b9a93da999141195e83bceb9dcd8552c1a1cd37f774045a3683e43065104f3e7dcb21f2991060cfee7869a31f4598d58151c07695ade914eabf0c1a4f0210cc016f1e232c89e1e5b13b9206d1717838505af0b703b81facf9dde18e90f4e3e92c6a2d29bba83f365a3e5ba772a5d5691dca154d564fe47a2b17e64f685e18a693b0936e1344595e7f5a2a6e8788b4709c8934f033f4d1678dc1883b8cfa41b66a43e5d55f4dcc7d65e794dceea093f1c45fe0eb8ea5c89204fc4d35660ea1242ea76c2f66e8238f9c249898ac10d1548c291be8a02a98cd5db52f4ee079f86d281fc1b6f29cb8658372e8f3fde5aba2c40e12609ca60a87e2bfab0bad0e585b02bc4c41d33bbb6eba229678204cccd9ac002e33dc601f893f47aa3cd4cdd8f7a5077c8de8d619cc115a462453c87764580a9197adbadaf7b1f30d3587a76a0fa7e5e2e099e3e11275069e17185d12357ff706b410065850787f063fed5fa4f583d270cf2b1d8d27f6a443519d3805419f0fd1933387c7c832f9c87d4ed0d2f579b2ac88c2711c71e3d29c2b743b8e9bc06dc7de0148199b984ac0deed19b405a273910877b9c0f7c1a6f507c86fe3b20010f490c1fd104b385a2b9cdd1b965c467a16a870262eef81fd88a808fcc78f04681d61539b63432838cf080dd21ba1af888e87986b5c9c35006ca28ec009b7049ee74d98f0627e11431b9c531fb104636a483b3386194679e5a0528688e3d541d4afd1830b94a03dd54d88038335389c828450f3392b13e20612d062e54d0bbec1dca06687b972f5fa0e850cb1be95d409ce04860b1d9da33e0838afe911b73edb5e03ad88764f71a65c21372587d3bf84f9d58591e50a05a542544d77fce8254d037c117cfa1e49389a9a0f2f18dc657b42f4e5fe71a742ec45ad21b8a32b873b86a4c987f1dfffd3d6321e56d9be4e899398bdb09c82f5ee8f36c446cb83375e56b493310b4f4f64b0f01eed194316ca07deff161203c4290c4688f7616aceb619eee6a0b5f49ca2b3082398a30a3d94326099e4e272434120a079b25033268745332fd3148dea820ac6321bdf7b8376c195caecf8ed11269588678315163003928d16b000ae82386585a92490bddc8d5be6be7086076518b43a8afce03a2d510243f3eacfb0c11fb7de9d1e5612f838107770b52ed0d48a85541b33d18078abf3951f00cf71958de5b61c264c8ea03660748eb5ee68195f18273149707cee5d783bd13d9ea4e5ec8fb6a9004f8e785bb143af75c805c649539ccefa42738cc845c26f14d5004fa9765518315fa74a79514b77412cc18d76ff144948e6eb996874f4b0dd595c3b222b3858283584c40255f2f5d170e5270388a410c792ccbe3c15d6f7bda38061e93f31ef1b13f59775eea6c4c760029e0e74619ee67813f7e12e38091f24757c0fe610a08c1130f2a96d7d55a993abddbea36c7fe4795738954802829ace71dd28897bf3f08112dd9a14e9dda394e8cf835199ba5a25bbd226aea1c58191d9d2801de64650c1319f83ebebfeffc33b5dd9cc39fd4745bcf218b1f9eb827911d5decad17bd49bd65016ccee6faeb78358457628cf14f33cacd62b34a7a5a2c9a08229b5593e381995eaf8aafafbb530ea248d78613e17cf5bda4f680472c3a7ba3300183cfe3c87d70b8278d46f0aa2481f59abf7e1448338cd86b06ffcea8f55b8d266c1efde5bb10d3f6ae9f844d8e7567d3db754105cc48802bf51cceb4bf1b5d31045e23ceb51d1aa5b05bc360981e6e53ea82684a2525607c499ac054a5e4808eeea18ece8c06db3c66a32d6783b957da986a8171ce55efc469b8bf06e888ab5fd51d6ed65abffa246a42cb78595bcd745b87c0db646b32c569f8024842d4d8c19786207091038c7816bd7258046c960ab7f59d3d6c07f14036a0849ed6229cb8d100f5776e4209c16acacb9b15899fd5be7fbf06c57ac3659d1b64002efd0cf53302bce52649d0a794961b1ca7a2124c032287c422920adb41f9b2127eb655dc24fa19ef30f5d8683e86b236d99f67ce3531d0faed9cd1e3405f26ed4deabc979a35ddf5dc46491dd30f6219d84150a72cb32bc0f11613a4415e03b7d839199c14bf6cbdfd11d2787eabccc6614bbe182c044850ec910ab70a18db58cfa559b7f4d0f64cd43b04946c2d6feda3dc1c2770953a4439e915864e3cb5f25a039f249b6a79747bf2a1ca340d598b5d981eb0ca3c169be23583a38c64168cd59e69275cfa568984bb53681a5234f4744fb254f058b8e02cd5bec60e9d2cfc4ce4772ba5c85950e2290195770d3623d52e2ca9aae5b1e4bc73971a4266192916492257aece9a5b4b174948ae75fe9005493158b5be9d040a308c4b274d8ca0093b2997e0b2b7c2377cb6710965d916efed009512b624b50b7739384034fb10f5185b9147016155761bd05e752c6364833a5b9acca6890c3206a5acb9feabb6702a01e89275540b7de0895dabadf039f0d51965f529eaaae641e7c7da33d92d0446d25ca31e1c9bec40b535aa1feb5ee03a158d169232c29788b5bd8b31c89de6bb52511987a1e24b1e5c3164c979df501ed11afe5c512fe2793a72b4461d07e265e9768839e84bdccb2cfd5ffc87a0b354099a5f018a9f4811d2667d144a533ac59689cb3e240b3f263e1c262a47727ff1425264c5aa46975b8a0a86adb826c646f0872e52735035fa63a3e9fd9c0a726a8cc5adf308f0530d7eb96a871ccabd63e00434ab9a838c8259cb0081edb12b72691d41a5daf3a1f5316101df1796a854004142ae2c3e3c5c83e03e06aacc2df9b4faa57a472392927d80ad75a637ef0a8bc9e79c5fc6cfadd658c9f4220468e34d6b68a1da6a8439a9fb4c76ee49f3a1d7a26210431d19c8b6a8a5ad16fa8d0a41d06a78e49c3e79b573f262c95c5212bc558cb3eab1ed0dd01ebdb43073cf203ca36839c58309cd5261d8d84da5ca9a9d35d2c6fe15d4200ae97a244a8375a72afaa482e162491949841d48e06e3c6ab2018a4318e6ba73bf919ce394077e5541ea7c5fe190a767fbd378f8ad6dfd6d6b6d1364b88344208d97bcb2d03e809cb0990093dd420337ee970fe0e2f55bd17d73bad0ecfe5731d9e0d892d4e2c3f467d77da8fcae3f9f18be99cec19ec2198a6611414b71ca3c7b74ec3a41cb4e59859c2f22b8aea9deeaa1bcbf2ad6ed316a555a857948fa2f1f1509d85a67a3c5415556113162cd36e62cdaaeacc67a140a0e5a0adae108bcd34b35c7bc1ec27cd8586d11edf3b337c839f56dd1b8b71180a8542dd1ec2426fb42c282d94b1d0e682e5eaf1a091aed19473b5b3e82ea6d4d619a2427b0bda4c28921eeea137da19d965b60c893104ced71ed243bd6a003a27878e66d7983ecb5b8fab3b68350dd334ad86d3344e8534d26a0dc7a990461cc79d4c40c0f060a2d3e974fe4d40c050218d380cd38e611cad096118c75dc3b887b06b1e4e53218db010f71017aab8900908189a8679b61d1aa669d8b5edd05e83796e69262060689eca711cc771216ec81cc9c45c65241303aa61f590a2a99046188769e7b49ae24040dc4ac1346bdb81bd460bbdda7a68163bc48926203418582806c7711cc76d18966d5a75968ae559d47e9af6f4eb74169dea96e304b7d3392a3a8a9e0e716e0202c6ca59aa0a69f436d42b21569eb1d4cb57e259966b0f9d858652f43e22767e855ee6829d351b69a9d467e0ecae4fa14d47e9a9cfc0d38cdb3ad0db265aa2f7c723625346c098874325bb0788c71dea9d97d5b46717cdb2183b33cd315a56e6881906afd49af918173512c198f331624c8873aa0e041097d5b6a31e088873327d2482313b0d93d67031e6ec2e668c5a33cfc568d1a1478c7adb72d7a1de1e89604c8e9b15c79de5a827a612a78eaaf5d8b663e55c6bf831ee59e9277025956d3b565e93d2e1da4a5555d58a0e939b73ced931664ba56c33a85d3d704a8f9457af94ed8ba27a278c7a4ff73aa5bef21173eaa9193a6ae5b352b983204e5cf969e5a695129f3b6d3958a8b493b2adece46867ca3554a7a46018860141d962bfe8b3a3de01e2288a1de2c493a91453474f04a306733b49e15a8332bba4bc079af21934e53eca8c3acbb6f5757f7b0755b78d87c7569f6d87e82afccc66e7eaf9c0962f9b344c767e43eabd56e26680dfae00bf2f3ffcca64d9cb81dd0e0638c39802fcf02c4b49a552a995a7304da55252b25849511836fe7c487d05068c8d0ab392e2dfd4b972c73bb00e6c83b9aefc26089fa56279e4b354576eb1426b605c88e52ac552ef8d658916557da57277a8afb0a460c078f5eaf9c072d44ae5573ef3a8da482baa35298771ae3755ef0a33bdb289459db9a3f4ce3cb10e28182cd58e5d896790e90c4bf764998758795579a5a65210a725c61956013c00cfe159c6f5d230cb57be52f92c2c9b5816d147db0e1b5f21d9a8d5e381a587b8c8e82725d3a9b25155364adb8ecac64d5b0fad25467d0f396954d94045b1594a2a45d9a6a4a4a4a4a460548e8f07d4296561ebc3bbef701d0eaa7103d4dbf5f002bc9c1fea951902637ca8fde4467d2500a9de295347f59e625e7e5f4300bf5d0f95a14b007a480e3d846795fdda78aac2ac3c55af8d7a69b591963ef50c6a1e5a3d1fee638e81a6eaa52afb4d9de5b7772cea353ea3875983f64067a4541b79967a5395e577a5da487b9fad5858585850293a733a4353e92918a9d43995fadb8658a9d5e3814feb7d297a96a3de4f604c0fa0de4e00f5762ff59e877a5f0250ef0b8d7a656c0ef5cae4f0967aaf96c7a877bed67b9a514bdd65d47bed7000d43b75b84bf57c5839ea2ca96a232d57d449db8ed46bb8d697b61e9a4dfde5ec583ebfabf7e2efc07c1d7272a8f76aa92b473d46bd275b3d1f522baf2c2c376d39582a69e90aad2ca56cabaa5aa1d50a8d96f26144519665cfa67d36fb0ec7cc5c9cd9ec5336b1473d457bcb917a16595858be832d4bbdb1cc422f1f45617ce537966da48551abc703ea333095693830269aea9db65463e635aada45f59e20143154b90a716092b6113f2b0ec48130095bec037186dc1f9a87edf5eef815db8a5e389d121cf844deb490bea984bc9bce9a4018328699394a7060532ce72831629dd8916524b08009e9778e4abd81211047aa01f206873c8abe34ccb5026358420f8dbe4233cad0c588226ca85ed4b9195bf6348e764dcc140da988d26fb763c69fe957e8a7d347a4d141f5fe4a19914ebaa9deabc99da4d0493f550788aa037c84ea233d8ba2ecc43e7ae37535f7fe8c8621bdff52398e7bd730a373e7c7d1cb7276ce48a493ea7f68977ee9f722fd4e991066926997bea9de9feabd280996d2ef87ebd8b705a9b2cb652676545b2efb18bad499eefacf05b35fcaba46b65d30af8c6d9986792fc2fed030a377b30e571d1258308555b18c0416a8c01ab12f96b330c113abd91d48b725cfa6a3b3d83386319b021847e9a1678fbed3e91246e9e57c4a67a8a1ea7d23aa6d3c3c96946d3b5a3eb2d83eb6eff17db4e57832f31fd175a0a587a8e8fd92a454fe2c23d5a3e89d36447a0815223d84fa0c44a590e88516757e36bea7a0ee84bd2fa4438f1c8efa4c87fe2e69871e39d41d669af448a41a0afdda441289440a9178db01ed7d157512bdd3de0411b2842595ee06ec7b89742314f6da348ad6982ec43e7aa1253d6e34d0864af5de88484789729442b5266e3d6e5bd34917a16a77b5699bf2dedf15c5a834e5a6fb447f0ff5ab6172382ae522692a514149292799502927855ebae832531b824443fa23fd958efa9be2f9f08eaadca51016f3c623b6f4167a9f6d3968dbb1c35fad7937fdb34349f4124944daa154127ddb76903452a9542aed2022c110a534b1594a2844d9a6a4a4a4a4844ca2faa6783c843e0375a0a6e74061dc43e55b5a421f02635eea31eabd6ad33744018c23c95ba553f55efd48a4f7a7f2572a954aaf35a4a34acfa0167aaf5e9b6b136fe83d54ad21fd54ef8b7993e599ce42995db6af506617d025259d4bcc25d24b7fdb10a877955aa235a572d343671823035dfadc41db4337d1182deaa19f6ca42da16e3a5d521874ab37f46bdb517a0daa87664b97811365ba56aa773b9d5eda729c3292b42a942bab42d992e8cd8025fd6ac0924824ab92d9d353a294d62159d6afe783e7c3b3d6ab8e3102ba2899dae4263d7411851285427d075b540d6981fa4d8992e87d967414cd5a23d1d38d2d510bd827eda93e1f3c1e4237d1fba8b0a1cfc0cca4f566d537e3116b04f67b91ea137e628d1ea2d665605f1603d54fddaa563bab413c973e3cf5d005a3f092328efb43d61812d23751c8bb811600c07082a7ee9ab9bbbfadc765553a78852183b161d872f5ea2d3e1c30a3c91198d3640b198f34ccbd9e13b005f33e2330f1e1a8e031142e944cc18a1d74a1832c74900697d730cacaba304f07a24882288a28904481240a254a4a00058a19661085122544209148241289c486339ce10c422082104a104514258002c50c3390228a1b441145144890cc200a11122990209102491437401245143310c960063298c10c649063e3b3ecf19449ba8b154e77f16ac34e55e455d186270f478c5c280263ae0a070dc33d564770a048e285ce3b12c58b9cc845efbfae2272ac9e9c32c696f26a98582f66e30d216a4005d3602b440d94b00b66d9b617a6b55cb081c916cee4f775bd17c498ee0cbb30cc8a3a47b042c749439d2358917304243469ccba8ab82f0e805580443c9e67a5b8ae6335d72dac869430af738eab6a445c3a92fab816883e886898ae8f06d1dd15d32222c5e31cf8971a16ce1cc51861a545c63011ca6ed891869430533c586ae2ed8d354573f8ba0c46589b0b3f80010ebcd00258bbee6c4b111cfdeb185152a3616075c48f77e44161032184958ca2df2702cb8f0396b90d96f914606d9e2fd330dcf9078bf93f02c69ca00bfce9fec4cc4d2eee400fd14dc7156dac4082d878ce386a832f01763c4b53836954d3c6e561e53fb4855daa6f336c758d9e27531d35ae03ac9434d3ca9f4ea753ce0c8c3902bac0e7e4f41188f007379a5beb72153745b0f1ba324999c6fb8b7ffd8a5e0a81c71a0d039f12282dcd043a4fd400c75a073d2ba1607a2c144ccb42c1c42c14cccbf2f66bcb01fa582b8ac05a9103163483b59ab0d6ad5b4fccfb8c8886e9eb6a0b051364f9990782815dac330aa64823a288cb04b39fc94d873c77474477d6558209371d6dd1607ebe3d2553523b11d8b51a440af9209108ed1eed3738de33b8c334ac4b24ccea5d24984c30cbb296dc67b54d07b4d2be224cc3825128dc812e5e0c8162ad5b3098efd9af4d07b470878979f920c2d0c5c50281e5c4ccaa04e2c6e3aa96f5f96d47b35030331a1fdd594f9dbab3ce56a53beba7285a8d43acf51debcaeabd6003b4da8019e862dd93fd45d3ae0789d7ea55e1b1fa025daca3aca7c45aed4577d665c127155a2e986d9de1339c969e2ade7b3ff5af7e399229b18f5fbf7eeff2000e8c49d230fc8eb48d77ae212ce653f2562004288c148992350bb15ce11693df9fe521edab34fd38a63a5f2ec5ca5c5735a73c9de2613da297e8aedf0c65483391e978963b883714c10113299c50218d44216e823e9b9669db0734b99068442a611dc85e675533df48e9e8b6ef1960981374793022eede3f5b665d9ee912ec857d19e0ee5d08e8f2bed57bcdd3a9aaf7dca4b34b68f0867c5e7b71a9203ec13080c21cb822093b5724218ae52bb0e880e52c8c2444f8ae58b223451a72d0c4122bd6ab5ac218a1ecea5d4bc876785aa78fb2c630bb08d3e83791eeba8f9313dfef268dd3384db49186e125c02c9c4e5d7543d15d675ae6b9d6b32ad35d6bf4076ba666eff79b5d26a333d6b3accefc709299691cda49da461f4261f26f3b996c39be4a04b3218d54a3a7d6b1a02c033f794110e1a38877ad605ef601631e0e211e9d71c3e4eb9af374fafba53d903d0fccb6ac0436e8c0bef3274bf5bb3427baab2bcbbab530b15ffd0cfe4e69efb40f6e1786c93e76293bc3b28d07f6a6357df9ace97df192c2d8f017766e241e8f076bab9297f07c5f64bfdff5d9884109031d4f8c0f8b3104d3f4d35f668a02634a153ba4371efbf162e188de173b7a4cd230d73c31065dde4d947aa6e8ee3de23431b163877f4a445509a9921e95c81aa9e8ee4df19e1d51d6b10c636014e8f21e05fb7b8422098675167b974522cf9b90171c52c09ae261233c8c47669a6184319e462358af2dd678a5605e18254ac3c4bf18ffe053f16c478f4cd807471442e9eec9c858ec997c03b2da80d1e73d2898f29ebf5f937273cf208944fa0eb6a41ad262deded848efefb4a3f8f990e8c68ea80544d446dad0fc0ce428dce9eec12eba7b51de756951203ff841929db706340e862e92de0a897c65238451ba7bef969109ab6582d98f611c4fc7728cae3e3a804f1ae69d8948e141e23697bd7edb327fe3f16c56c1d6b18ef08df8fec58259fd4227f655f4f170a57d0dc3bedfcd76559969dc6891c863f4823ab0ed830dfb310da6f12c9cea091cb284481180708509a2e4608a1c3861790da3acac0b935aa0a93796e3d3594113e76ea9c5ec31d867a30d938f44769d5bae05c556d5667533badbfea295e96e86c87ce94e66c6ece00aa60cdf003157e724d8aae22e96d8aaaa9e98d615497062b75b1e7b65ac135824983be2b18f68cafa9c716471dbe1b1324c4356313f57e6f306c07f6a7f030de88fea063e1504d5b38ca357c672d939b80d617dfbfcde5e178c29fdfaedae97a80c74a9441374d56d3bc1dc3ee3332d23aab3deb963db42549ea3353f642cf61f323daebcf5d2305bd5305b054d1068cb110a519aeddc45af676be2ef467381ae3d03d1976e7e9bb566030db1dd42f2f9463fa3633eafde358cf6ea1ffa43bb6c97ed5eb499d59fbaab4e3ce2ad5a83d5d4ecae6adb5fccdf2904ebc8583216942b665738e3c4a1b3a735e57e8748ac0d091e3d3605bc1f32b6b3d6ba5e9af7d603f65feafdb22a58136bf44b773cfaefafd6704dd1bc54946c2d23f3745faec7dbcd08b5c0b9e2090cd6a0238215c47311e38bb19f80628c31c696f271d154e87a9f1518c6c9f3a1876c678877eb2c3c292b59c528636c2731c62a4619638c31c6782746ae370cb1909b99463fd3d843240e49395d917dcf5efff6df21c3c4bf5b0cf3eb4370cc85e01b9c8547c0c770ea0284822de25d5588571d99f22f3e7e107e9869fc58e484f8cb0f8f5d1c8410c24b0a462cccae23931f177c83db09dfe0e4a9b350dd081863d57672d50ba261275fb0f005ba74d005364c3c94f2ede4f514b0c8753bb1c0cb16beb0d28818017681c72e0e1ede89c788f5012bcc60c51366b0e2092bac806205142b72e005149de508238cf1578dddf58bf55e578cf4aae2bbe3b41aaee0c434de9947f5de749d15892e2b12896ea20ce745d412d1cb42aa75f73a1c52ccb40f8e118277341bcf7fe1988e27c75c237a4776740474e9ef741be6e897777270cf5a24fa4c8b2a92d03b54858c704831a71030c607e8097cb9723cf59ee655c9c950ecd5dd9019ad13647c287f19126def05a3308d1771a2287911a731a6f1feaeab8f710c73f4c1978601d8270017fbae14fb2ef762ce0e18ca60cacc0a6419cf77c5eed84f02d9cb6992051cfe9d3225e54bc344dbaff1c476cc0d9cb682073a96756c77e3b85356f1e1307938705aa04a418ead21051f04f485cab48d86cd5c9dfb335dc17e382f894cc24b120f7d4de8cbe9ae1f4ef73d5895e2bed8b6ea63018431026097fed5dd7f79491e4e77fd0b67c6fe6246a703f69eec0b8c42c62d1efe8c864955d6e34956222f47083bb0b1f2840c5fbd5a7691ec424077906fc40b46010a7b718e0c8ce9c30701ad88021316be056af61dc1de91ed2b06f35e3e94c4c05e7632f3ba067938faf0105ed59359f9802ef0c71d6df1b2deb6e309818058fdb8a3ed7af6ae20ba837f9b05ad3a0383f95e493564d6b9e5c214bfb2d112d1c367bc0727b498d74f173d6369df96438561666523b5f2952c634dc4048a2dec8b6299c90caa7082292cb59cc5098c681af68ce5726266df36eb07d005aecca03d1c4201713a46e631bf578d73c7cc7845fb09bb783c4fd8c5b31131e30149acf5cdd2ded683f4ce348b563b739426fbf68a6af506e96e3ef3d0ec918641f5ded879cfdf06e2334f2738c92eb71ed5b9bb4fbdd1569e73d70a6e3dac6fbdf5f054de7abc6fd7a62d99af3a56dde7f99cda9bd93db4aa4eafaa7b7ea2dc2e9ecf400fe54a89377f9fcdac9643fb4653d5391ad053d5e73f55a599ff68cf385a1d443fd7b4cf375a81280ddff9abfd730f4dcd4a533af7945669e6b9f34d07a5b673d75ed194e8a157cf4c94f4121dfdf3f150d24dd4f312c973df5669484f7d3e0ffafd7c3b47531f5029057ae89f97a876121d7da3a397687692c6483c51a5e19e027d5efb05559a79edfced598882ce51eddba4da2b0a7a8856e7e89c5ae5677908c0bef703daaa2ad1f63dd372803c2b35cd08f301a92e7f51be45df67a024f59051a36210bbb9afd930f4ebf2788e617d5de7aecfeba02bbbfeb9be5dd7ae67cfaeeb8911f0baaecfb4e8ded850bc4565f609a2b7b3d93f74a31abd97cdeafd95f63a467f64f04252fd6d3bb27e241416a2afa6f7c7a31549ac6afad166206e18ee072392f8b82129721cb10a79e9fe83ed8494e191114fcfde91d37ca719812e7245c6f957c378cea693f543c67b1b22abd77efacd117b65fc07efd8d32baa999e59f4c21ca0b6a80eac5ed36db2cf4021b6ba454114c82359a42ab31ee3bdeccbac478e625766d59aeaa46755a6acded88bd67ba351138954fadb72a4a00a29d4d72b4b24bafc27c7f848bb758d7b557b58d77abc63d79ed11b6d06aa345865eca61fe073d0673a01dab19abd545da3f1595653d86fd11476d02dacd260e7ce55f71d857dac97ce5b8fcfb15af3b16cda6ad5a6ede759e8a68faa8d07e921ee6e7b8c1abbdbeafbd77b1ba2aaf7b5655552abb4abda80bd0eb71c2dbf2ead5e7855a2ab8a0e45a2bf614455568f909eba933b54ba932dcf3889496a895b8e962f6141ffa3a07a63eb88b55ac2becb82ae7507d21ee9a7ff0e029db71ea0969bce55abd6b43c6ba91775ad9e31db42ab97c40d96bdba96b0395cd38e3d07caed02c2aed1cbfd7f4a3c6bfd75ada99e1d6e3c48cfb21b5b555cbdd993b0284669b06ad10cd4a2725056af109bdd64ca5a5ade424987d7c69a7e7a97b0a6577a356b3295684c5555896749871b0dc9927eb2b61ca63f71d25d163a394cdea799d0b4ea560e9f5feb1aed26507b93b8e5d0e295036d236d43b4f5148f0a1ca9e3d9aa9a680a25d1c94510adaa59cdabbb140fd0ab57b605462c47c1321647a8b03a32ed55adbb47d307cd0f1647925817cb58b0000e96371e59459243bd4487d54543e09617d137457792893662e5b1ea6c3fb72e8afd536d3bb003815f641f4d86c7088c99edf2de9da4e686794f5711e67d46ae6831ec71fbd48a8b0a7e31575e6d3a9e35bb2d2a4ccf57b8bbe78412a64684793ba78b843611bc5d17c9b25b163cd230b7bdb0f25232d1302c97514228ac7c0621e802a0a7fe431515209e0c0182012096e5645c46bd178096ab17742096e52ee3990c5acfd114144a06a5e7288cf73604e82b87441a66e5f27048c378e1011628338d2407106f39b87908332332ae5f1977792683521932cec9a8f71600979d8c7a0150a14b8545ec8545b833733ad47bb21c64421e1691285882b3c472076d39b8ac1fd41ae748f5c955058ff00d6e6969697916df13f3764e117b5dbe99f00db6f2f37911f68b1f8e7b0eb4993408648138509d1ca88522f1eca43948487b3be7ce1c6cf518b4abb48b50da4d9c360b4522da15aa04b4302a7767ba0a5502daec290ac4b2993c8a2a016d8ad4b48a5ede91cf3a47e7300d796d087347b4cc34b8df2e929dce26c3b47e2fad3b899dab0ca2d15a3f78c75a952587c037b2cbadded39580d6faa8a9268499d330dce53b8bec3254eff5d9a448c20ed1ea59176926da48e734936ed29da5d3d00d73fb5cc79b5c88be24ddc9148faac66acf087d4d4c0aa2cf89eee43f7493d7e84bc96ed239dd492ca6a75e324a1be655b9bb0ac74875b5c85a03730e653c20a394b0ab30c2146f053a506c73bf9630625764c6989788479c64773ac5783a35a9175e6ab7756a0d98b7b75affa2e2a4640a2186b7e5b042c0180af4a17c3656de29229ac1ca2a44734e1c9a604f8047d408e208cbea1bd1f4887e5fcdb3deebfdeca2471821017e12fb5743238e8042c8cc5ccd0858fb5ed71519308dd039a26124d0303afcc4c7fba180a10993292c63f18428efa3d37bef976bc284c947c618bbe35f7cfde27bb0f67b0f07d9fb186c601f8be52563b8a2a7e52564e8c018bc004f969790a18a152862197e5000cb4bc840054902fb2e7acb4bcac0821f2c2f2943132acd0829515821cb4ba08061c5f212284ab89690a109bb595e620615dc0821943760a01978547690a52c2f31c312ec4943595e62861d7bda362f5c2ff0e5084c7022084ec4202839c253c9087b035f983948b01c022d42a0e359d37c6fb6f855c564e52a3fff609798c61b63b2d32a67d5af5abd114c96ccf1067bd207f1f2c6286394ccdd49e620161e26e690f7da62b3e0f34e5b1dbe8636d2be7a696b98ef2c8438a367bc192d2a1aacfac73b02854d77376655320e6897fe05af59040fe61156f4d1508a27f3c34b6729e994c81d5491c5888d30beae53bff71e36eaaee3d9465ad92df631d77b594aee032b6240c407b2aa2e86f0d69fac0c23ac57ad465abdd5a50f0daf0ac76b3439f0228c94980c2603218410420821765955f8a15da04cabd48bd70097508507bc08029320e8bc7e1c77c03c7ba667da054c84c007377877f3903d9e0cb587c4b351d61aed025fba934ae6cb9377df8ece7b3eb670529f4e7744dc5e3e989a1a66bc9686f92af8cb3a2fd8b663fe05c66497f69255223cd7c585a7d32e97bb783a1a1a66ca6ad00898f39e9cefdaf5545a6094d7193278762223f3c3113641f0999d58e62ef89584fc98742ddd719f78dac0794312223021052640c0c19f1c734384074f904ce1091c60c20e70bc215064f2d5e5dbe2a5a4413479afbba1dcaa5a55f6c7c8c2f86ecd5495558d38a26df46512b8af6eadfad0edc556d7bab62c23f79396631ef30deb2d62ce56bf5cf58b31d3a8eafd31b2f2b1c6ee2447c8d64dd55515324da68b172e745c7c0bcb308bfee13463b65856e151c7cc4097fe7b8f263e1c714bc242cd46c631c3dddddd40809b110dd30bb0f03934c9be57122661e135106f2c338d9b775921a4c5848fddbd7798b297e5c34c7833045bc9eeee8b317959315e922586699eb8e5e8867992b1df2b5acc342233913f9889ad7690653c995fcbe41d331d828c6bcc2a34affcbb7522525c55f5ce753e7a1ac9bf575555d54c4fd387778dfa34b2d52dcbb21eaf9833261129208c8c6bcc8c99ab9786812772597fe93e56d38f97c7ead59d7c4809b3cf164258a5bc2c7ac54ce311e94e32e442a014f65bee5908f4646053ef891802d11cbba7d6c45fd6f31d6c4d1588a584e81eedd1f37ed1e51f8efc834244a2570928a24878aedda24800b12c90256c8d566da0c56e652f4423bdefda0874030402d5fbae3dd619f88004b1317222faa33b191fffb67f26f7f9640de4fd15611af2d5239886fcab12e84e7215c9ec4f9540bbc8476a019b7679f419794db48bfcb5ed78da3302ab228ec5fe9eb02f0616bb12d062bf8c052b7ff90910cb5a299aeb5508dc278222bab30e83197d1411c262c62bb12c91937ef261866498a5d2e74561ee21f67d87f9398991b78062096039470b1cdb7f5074f7badb49dbd062dec6d1b1cf3acfc6b056a2e453916c9fe9c681315b6d23a6db62fbeaee36d2ddbbc9481fe937d1479c68180b78de4ec030ccb7f34ef02ad57bfad46bd348b67fdefb47ff7cb66da42711ade9261eb4a64b879b0ed04fa75a2a7df40fe94dda6a4fd12e2fda8d320ede46b595f41694f055e10c55229d43067bbd1daedac0ce7aaf2d7e7e54249bf6e43909d24a22913864078a61dee7e45ac27cd242fa465a5a1ab26b74a31eed9322316d946d95dd254aa592e74dab5b4e70c284afeef1782a8fc7036d4dcaab5ba6ea01962fae679c65ef9ad5d4aa4f1237f6e6f3b9e6f9f09df39e49693cdf3cff98e6fc08b1335bc26403e7e7e6d9b68cfbe7291d1a76b69e47be31fab6c10da2b60dc2cd0243ac0d4421317d44e54dd4066e9ba669da1297f39aa6699aa669123302d3300dd32ef9d3bc24c76ddcc66d18ade130ec9e739cb6c15984dbb052a9b444896aa55249cb608c0758bef8e28b2f7098ce1d737a56411eda56ef12f0e2a19dbbab201253e5766166ceaec72d8785e454b9b9634c37516e972cc32233fd4620ef371ac0648053355d9bcf0cf4d93658fd43b72cfb67fb5c23a53ea06d4b850e7af68aa6b87f5e793c22b86d9f0ffda6b64a331f02fd43539f87be3d2bd1d14954247a361265483c9b9d8683dae7da070ac0be27a18908a28a60e1240defbd6e2c9cc021c628251653287259460210be8827888da31bf42ae3781288f568b481f6bdcb9a75c3bcb720cb32defa5c55952565f578e84b5ac5c7c37bc56ffa28dbf7aa57913e2b63ffd14ef17bc7c22316bed7c3b2af2b104b3273bccdb339de61ff463e29456b269838ddbd4097fe75cd793afd10077bb9623e2b2628dbaee359ecc3dd5c74f7840bbdd35d6098130d0913ab3009d498cc68652a1f35175c38d942ea7016b1ca260d03231966c5e9ae7fbdea2ebb37dbf61b1be365a46c3fb57a3cc8cfc099dea8e7925e5d58eb17e2bc74d75ca861de29bbb0fd87844ad79f11238c518918ac7c89462c8c95910c0719b73c1adf9af4224681696828cfbe1a63bcfe6cfac2fa62557a687ebedd739ea7d245e740678e21dd3a73898ea8885e8d5d663d590f613137ad7a0eb71db0d664157a3cf55ed2c69aeaf0d77553d51a7969675a5a59abc7437cd5e3e13d47c8d32af9842cc3300cc3304c8e36cf31ea7986611886611886719af478300fe6b9c7e339e6c130cce3c1300cc3eec112c01896b1ed4116cf177316e446d814e0cfc067558f48ae67925200085663bb74530008338d7bd1885c9580876578cb4b8debc2b8e1c532dd5f72667482d01122c7874ece7d2122a786cecccbfbbc278e4faa27b2f71e7cccba8e67afcf3457d452c27cbf6a8d1f5ef8f05c9580f605618928a2fae84e87799e6890710b8c575b22de7bef3d2b88f767bb1f7730c21cf225d21adbad12c4f08436123528b6df8e8f17fbb2f7de4ecb98dd1a3683f5be63efc542ebd539be9818e766f26262547e2ef33157e5e772af2c6c9f1fcc9b76f6b39859d983d2303d6ab1f06fa7bbf780097fdf8eed2ea0e448b961ee70e1c910baeb9883832450449ce8c4919e02df48bddf4ef80663616243a01cbb9339388871ed0832a761582a9149b04862fb5b3811c1d82466d15d3f20d142b60fd6d805d3e85b816fec7816f28d8c6fb0edcfcae752e65061de084552518469d9f987533921251139c48b28dd754c43777d1dcfbe4e49205869e7531894439039dd41c9505f3943d2a3928a25f3761228a213478830251530264259c96a4a17a11ce11d4905d3e8738750608ca402ba3421a1e01bf0bd52ef957d74d021d58430e51024150df3f725938659795f66d1302aefcb2d582eca52eaa5ef344289698851e291e844c4e96eae5c6e39542e573eba8ed74ef8c6b37d4aa54e77fd9ef2945a93423a9554c82174d767a132a7bbfe0a9530a86c426516d249aaca2dba234527baeb8853e391eefa0ff5471452d15d431cad8ad9920ad88619fa95928acb6699a4a2af8beabd5268887b8b7e4fa3dfd9385a57edbe28ef212ab71c5c8ddd61b7a8fc4527452276df4ba399a462f6cbeb023b769d37212d38a490afa8fcdb810f8abc34282821efa68aa738b4b48020e91f3ae7687e46ff843e29696eff7c46b5067ece9f7a239a3796744ec6ecf3b94a759376995ea5549e023aea30b87fce7d1b1dc2cfb96d561ad14317852a873ea25774fe01409f9fe904700fd5101693fb7609cf5112e99f9a0a1d5ef4ed1f9a0a7dfe13aa34a1500d3203397a45b742a07f4eaa212ce6a7dab4053d546b409fb546e59fbe5c8ddda5bed57b18f4469bf26ae3f1feb9dc68542a7cf64fbda81abb4ba9cf1eb7214c37559f4fb555db3f87a67a3760ab675b0eed55f5d9b2db407baaa767f074d23ebfb87abcb6699b1647cf46d4f49b101d9d1b8634a2a173b4a1cfa4a08fa869f450bdba0b556d54b56fdab5698e5e4ffb6822d1efe87cee1ce9f31da27adb8a3e97b0a57325caed12225d3439ae2af1ec87f419d5ed49dc58f8cf8786ce5111a5e1fef9d06d6a9eed23043eab699f81ef198dd643af8de563f42e11836472cb216d1a08fc6204414ebc6bf750ed1fd07c965534bb8756df288de755bdafc736b3cf3d14e4a95788e5eaf6ec235d741215d68a3d48175dd21ed9e733cfad23ccebba758409ef392b01533caabfbf57c7c2093b3686652c9ac0a4e65da22bd1b6c674cff58cbf4dcfb6d1a9a366fb685a56efe79eed1efae16ffccf79d28cd2cc6b9f2dfb08799b8e090a02da3edf6896c48dd5ae7d5e4a874d671ae5f79846e942ec7cd7db56e38649e2dd7791586288f54c0a44889dbce99849dc58cfb3d1fe49f1f07c7e7a6a0d7f0b12c4ce4f7aa79ddcfc462f4df52d6e9e6ff5d26cdbb5807db27ae437b99d0f8a93bb876654835767cfce67f56667be31390cfb3ca35a8d9fd062aff1bc6192d67852f3f29e633435ef3906aa48d06ce7cf4a935dbbc7539568eba1b988584fadf9fcdd24fae7187d43acb6bd21f6d17ffe361ed949ef8d467492673b6f3c442759f7d01bc45e9bde688a26bbe8d9454f08a23ba874cc16b5558e3a4523000004003314000028100c078422b160301e9296b90f14800c99aa5274541787410ca39031861862080008080000008080608011023c0a65d02d969001976e6a5355da80b189a8eb43e7769e705822ea65323676c4db6ddaa9a1b46cf2430c41c09125f976e5af07f9b3f0446bbd18856ce9baf243cb0d5456e32682048006a58d1daedb259f775a8c260cee071be071f186ff81f938473000a5d969435a9892cc1d35a671bb400f457ac40eb709f6c2c9b41f3d5848fc42e77b51cf57e0494a1151d30f05ae1a97891f8a7ea857b60f35a52cb143b5a701db80f59368aa19491b4bb227ef04999e8a64f7b7f8d479134f6c46c8f53a7de5d85156b10bcd924f3a3a03abed6da612102984b99876e4d72afae85a17adc67c6c1169fbb5b4b5d5e2e3b519d39f9f879a1449931f8af306ffd1bfc8677636b6571de673d3e15896be10a2e9c836acb7097e9a6ef0dae33b05db7af9161bfd83acdb6671e4cd8b9aa22c30f761b343edaa831947b6c178864178f34dc246abd1d2cd81b79406c7f52bf30b390276176ceefaff7ff8dec9ecfcf8cdf87055d10473c0688483105704ba6e8ca22a34dbfc262ce67149b61a5c1d2ae417f24bc4a1daa1e9c0bc7a31b9c04baf0e22f61d7972db5fd96e180c4dd8f5c08bab8a931e63f40c10090d95ec2988c6d750d8df2aecea7cddd225687a73eddfd5e4fcd0eec6250d6865a05f95120b88bdbc36505e6646345466f459f25fdbb9485ab7d3673b4d666f94c1bd7aae1f3f6d9cc5e848d85b565a381239e8c1008b520158eb068ea676dbb8f16073f63882e7c03e7c474488ec720f3a60c72ceebd582e73819818b742fcb61252e5dfc3f015bd9249d8c3395ff0a1ac645aecd1d83e6108eeade167c6530538f0486aa4086c9a5e7c06fbf2e7e53602b3342e48d1958d2dd64b644d36aa4dc033d7548a3a179c28c6f1bbe4cc3ae89eeba1f719ade81e8d9290859a4cea7aac80c8b3b3933e0785d21cc6ca7363e6c8d46353a74e3c288e9cbd31b6d0c6dc5840f9d50d5863cd376f368b8ed13b8d0d63530b80e5613f944b4a4f01282811b610445eae5b07e822f86fe8d21eeb6a6dc5d2e456d882479cccc36556ad42839de4556f2c6e25196f499dd24482b85ca56c6a18f0e38efe49907e5e334219ccc839bcff50a10068a8340b69d2e5c109e609cbb0f00139c3d52fc59b46ffd98774219818d160366a58ebd570871dbe958e6198505f2a9cc854d2cf36190dcd52ad2783fe5b36b6d60e65d7e3c2c6aa88ea8e81b46e2771cd673d6dc32232d93b2c5a40c06e1c4b9347aa21595f45322626241b4b66ae0113b9b10f19a393859ef04daf632191898440adb25ce39b79da2569c87412d8ece15172150187072c9621df2e4be6fce5b945f40e480e5b95ad343b1ef6dcf8e71a9bd3d6b6d6cb2d5ca77b6595196c53a3b2bfc1856a925c838ce55d8ab1273be04cb9062c0d55b4d16ab40e4bf7964e30eb2b64fc8957f844388304610d0e5e7308b6ece323adf16b6dbdb4bcdfca619b515981357a72b976a7a923407a40a9026ad01d0aa3124064dd12a451cc52aa973114d480a1bb7ae5a04649718d894ba43933290028146c975daa5f24c52ee8d8c87c84785fa366541d367a2381d6ba76a7b6eb9e4858b8051147da03ed0a89bacb877ab37803ac51438b9c3f99b4953e7e8d1fe20fe4fefc400d66eea4250c871c6fd3b3d4cdc4e9212c16a234ecf39f0713fb64435595d2e8e7ca3c163dbae23e2157f21914644b3e84d57d99a3417f47834461ccee898664cd4887f486231ca588321f39f91b1a1ddbcd4cd4364e8468e433922dd55d1831c2c63704bd1c5317eae21133ac98e32f012dd14e6a309867e8488ac58f104552a25726ae46b0a892c3056a0d33c33bd2f834c497581a95425d6023e0b5466998d053fb29f36ba97d1618992471c7647bc5fe1d64d61a0d549f11343488e05a8330dab4b86d8462546bac803ebb17a3609e6ac48b21828d710837db97ab1667adc1254ca14af18456daa0088ce9a74e525b7e21537d8d1c51366870686c9b55be3675bed926045a129d5a18bad45a45dde77a957f334c7263d0c5b6a39c030f91b375135d626f3261c817f902a158f6fd97b6f80a80dd9b2915dcbadb6e39d696d1cb510eb0cb06928a6fda8178bfa29dd3077d06b4d52a66c8051f2ae4ff683b09f000982bf709ff9584ea2f865f75420f8630b2192bb960ad3dcc0d9d9df0add727533ca7a7a1cd8803bb05612a7c0de7d084e8533e01f0d83bac708320ce24495b5bdba27273dfcaf905d95d710f5d4c174bb26c33cb6c71c464db8fe72df763cac340996d77f02d17460092ce021522fbdb54e71afe0383f13775d76670d8484586685c61fff78ea7668c1215e355198c86013ebdbb7afe576685f7f703b0aed1a2b886bb441c4dddd96c688b0c7e529b3a45e8ef141bbc0e68b10a03224e17016984354a32a9922e665192efec053416ae69a474b0a03be50a1b194594f81b13f87f93793575d29998439559bd3566e8002dcc683a015218ed911cd7d9a43205c5b1919a3124a83c4498084deb419f9e134a770de944fba2999e2f62b1c8bb6164e555c8879f728992d4bca5c347c6d72c1765fc1be517abb2410ff3e760d024a272452991327dff68438b2d50da502524e85ac551cbd4cc4a561e8cc3ecf4acebb91ec33451647a57e5b9fdca800e350e639afba8a6e1a8b8094f8d38574dc39b365ae147b54379f731489c403209341e9887251cd11d4cca66153ea0b5728951d482c7b3c1deb9114f81f13bbfe50f6c2ddc38a2d8d16bcfd73b7ae21f8d880a537e778bae92f43e3a2cf97edeb6f64db442efd720942f1fed41c12eab8c4dc5d22078c04961b31bcc4f5d1783d7325337c5a55b940c05e3d13528ab9d08e2a2e9e726d2447d2efa903284057456c59bdb84a692594a1475fa544ecc7aca4e7f7f95dc34ed4f604734c72f5e37c4913b9cf7a63a5c9ab3ff40e3f72cf48a1020b723e8c0ed858a7728dcd72f3d81b4b04ed7352c21f44c52bcdb49c81333dd9c1caf0e899fc66fd7534ba59495feb80c8ef409509aa6ad76d435f496288cf98b1d04d82b016bb54ece34d52ab2007072b42f519d0149efdc434a5e714c90e8ef91c3441debc0c3ce8728ed951a3eef9a89a047304c406ea4e2b4774041a7cec199d3967131b8b18ea6f3080bf24e492fecb7e1ea3816791d594f277d584745bace2efd760da8d34130671e63c0db2c44bf883a08a61c04143169a4d4de422c411595f8464fa435b58102ed03c5fb297ac614dfeca9e6272544665a64d13ac30fd8d54669b9a498bd9dbc1d1a11ea083b34277d47852d2a59bb8769de18484edf1393bbcf4cecb91fe4028255924e100a7ed0a53442410128bb93621b5e046342e82ee29537c674b0a5e833d7b999f85c620d718dd90847d2718af7bc477a42f3278cd738f4c06251a94a0cc0fa158ff43c9452fbaf2418a90a9648de83d74639e8afc0ccdffcb5e2fe8b95688551bc16233dc421e695c37880b3c2da4f7af40b7aacdf63e959fc1e3d62c223f230530f0fcfa1f127b3d1ebc34eaa0c537aa45de8e12f1d41d58ad0ab39c984d2be81258ba85fdc9093d551a4f0c07906dd293d2201891646d20929b8d293f82b4b8ff31bd534e8f4255d90dd23e4ce05542b400cb8c024010dfe477ef68bb3667227c9edf11c8d97305d4aadae798c3c576a56db465fa73cae82854ad9303dbb33d950aebfdd6263d48b6e5406ef6dce72cce4a5864e0edf0ad1497fbae8c881fb1253c477713794454e619aa3ba7c7a5ccf861e1b6f93948aa7c0cb4be569cf714268cf6c3702274b9e4e241e0fff87bbb09898234d23df7cbbb4a701e612190d632dc11dc923785ff693ef6b6803eed918ef65c9035b5aec6a9c33087f8e158532798a1c7e77f200c6e1c0cb2a46c1752ec17b6159f4eca6ce94b6cb8352f5b96e868641b6214205c2b761eb460ea1acd9cdaf9927c7e5a223d960742af4fdc41ca02740728d0a7e325772c1d07f626675322360afda936af020fc560513fcf96b3edbd465f5c7b467ac678d01114b66f4bdea04ed859ab55a066f981225761659975c1c15feb1043c598cabbd570c05b5dec54f0ae898e930aeaa15668c14c4346c7a8dcc78382a25d374a216eab0482269631aeee4519df4565de7b2bf9899dbaa7630b6394dd35f10421a17f21c0f6be25e5cbe67898700dcc7a431d836cf3095d02cae9b07e5708cfdd4526dcbe649e69d4744fc1512f93bed4358ee109ec99a709f3e3ce532f21e97bcf1ff1fda36264a161e7505faebf55efd89c6061fd4edc8386fba25225e1aeed4bac8c7468be199e36542cb7370a1cf37fe7643d8d287004b3374f14d8953c71214f8b03979521a8ed69887d32ad177c076064a7e6a0f69485b5ed33b19a09809766e49f0868b22bd2b7b012b73a25cf043d6cf52379c9ad02c636231f33ca7d9d54eed710a6f5110bcc8b0b60aa3b4a087ab54c0c138774ba9d60a7e6eacb1ee3c3e8df570fea9a70df9b86ef6912dfaf7ae0660ef7cbecddb0abf2b5bf27d4c9881a48586440e449b6102df65b35f8d15951f44b05bf683413adb2fcb99c75a27c3aca4bc2af4f695432bbd5948ea7d73416f896c7f7dd1f86d26960c5823a4fb3a9ad8e559019eae6f849f7c79d2b394ce24c0efe732c183e27ac4214c0f0745a1100736620b9127a0864dc4b805bbbc679ccd2ee2a3127c7a3a5dce6b6a59a1e10fded4bd6c3e59bb74e6a0bd8a15d825461329b4bb72d9cd2bd71a21a1bda81e288c85de5fd09289e10cef83ca0501f8c59f348d3c67b01e60aa174f435fcfa89ef82cc3140bbfd8429c433038cece94206f7661049d987021545584fc2a8e25031eecd827bd0bd2cc936c04607effd9c4076cc238bd5dcb1ea63eeca06c3df03df864ec0481abd17dcf2d020f850ca891534095e9d8a4bd11aec268e534fc61d4dc832d5e4fbdaa9878b7e8d86da37e2a46b1496b23a7d7c074f17014742e0759963c4305aed9a5509bc1f180fcdad2e967554f815fb9c1b81b3d12032c16ba210c26bdccdc36961cc9f14fbb1913d62d8515fb8a7539ea33811043f88da3d6a4a8b452197ae09f812bd7877fd9cc3ee1f7748499d4916bbd3206718dab1150af31e187111a93ac2a2664ba32f978533903f72f596b6f51bb50f32679d7c8d6e7de3d2de7b7d4722bcd1429e496818273ce1db87ccc3d002d170b3ef3b1dc412afc0c644319506fa188f225d02e4749e555c99903467b0f3b3b3b77616b11056473694c9b0c260f818c2a2ef2e746e618347317dabead1ec4018756bdf9516d7b28b2cb90086083e919f9c800551cd9dd8f886a863407c682983ab674adcb4bcde6087e8c228ac49a8cb0d80b45e0ef46f115bd4e162cdbf5bdc71261f38d3fb70bbb476ba8a77b31a996a76dae0806322849daf5c9fc5bb081860d3df7507e5429c837909c67f271a027a63b22124d491f5f3e37fa47277bdd872255b20c995b55a57f2877cab487b9a9a9b4b0e586f609a5a5af16ed7383e17115602d2eb94efa169c610a919949bde683224eddea5102f4bedd6486b0901fb9478e7345b0b0a45ece58dbc1bc7e42cbb37f6b2f0fdada5571d4972c57d9c576215dc98729085a4ba2a0f6ab764b951d904f8424de6fa59ead9e4cade30b293d1282633f48a9b2033985bc273693c3049a775613ae7e45db11bb186a92810148052f34436fe30465b1ca571cf2725079bbd4622475d1c31f0f60e674fd83173c02b0202a784f9d4e99aecd1d93466bef78845da65f60d2f391394eef4a7760ff45a4ea9ca081e200a63dbf43f5cdea22a509660ea8bde3ac066380f197ac2b5f7517654f3a27f2a2474f48a85f6299e114bfeba6110b10b32a4f49d6b3a0e1ce13c2a46134d8f3e49a7e7b6ec4f3a9b8ca056f5c612759b774e52a4c16bc2386cbe011c226f43a098e1e03418a033229f612fbfbee3c561716d4f158236b1d899fdaf859b1500c140df3410dcb848ee39d7c50cd5b479454b1f0bf1577927b2ff247dfc3818fd07d30bfb24bdf17711bb45a71ae8d887a69765794fdbbe878e8ba7ed293b4211de1c63d2ba655c42a4ecfb0edb0c0269a2775a5af7356f5f4a6f916338ba60b780fd029920dda678eb7e54bf15458640d379981b42154817f66bf44d84c1bbc9363f5ffbd68dced91aebe8f4b632bafc8427c5dbef4d594d7ec60ab2995f178a68a0e777bc9f415d4db8239fc7c1cfba4065f0489f5491c3de833a5aa700170cfa429e095c9541a182118e1203c961957fc27cd90bc7b80373df6527a728f5f665cf05819a9868c6f0e13e4153eaeab2e7bf084f8c485f1855b6a5664843b0d4c2419f16ac5a5bd5c7189d3b7b4797d75713801dd756b01052f4c0951881e0ee80b4483c971f748f6119278e2089d4ad6522f1cf0e077079e6e9712631c2eabc32c938d62dc67e5ed0924b20842ba6342ebc6826e08e285973bc2625e4059e340888ad4dacdcc718159e3b5aa14465576e7bacf23b774fa55e627697028174329251b9082e8359ff4b53ebc992739efe04d09e26a3594a4d60e0ae18a10850689742c5d5c255753f794bc2146ebea8678c4d52789f8ae98980e20159545c49fe8c64ee50dd583d9cafa364e4880b663bf84a1a507a21759bbbbd277647f526a7cb9758b252772a6c195353c15a3b05f57b36a6122bff21244208a3c04edff3a9e5af50f8967667c1493c00bf908361ba7a86e4d235496837ec33ae05bfd3a665c8d78b1a8567eb89ae64a5348044c7cc4c0556f0b680e6604f041621e1fffe8608adc27624c4e7823fecf0c07e1db83a313a235bc30b564108d31f2ed6df677277f9947595136b42296f2a938b01dedfa4a282e051d6fc44e3c282074308ac65539943053bd64ee9533e65b7fd7ad4c60749b7d61515fed7ccf325726a72ac148900263e4e981286806cd1b929213ab928c6c6cf1be8476dacde3378617a8715d1b33f6bf327d8f112a9ebd1d0cfe907b846220e0c91b02f200ab0ec5f95fed024f420daffb9bf8389b1280b1449facf55dcd6cf301588e24db6d9fa888c9f35f740508b42a7d0ddbbdd2d3f336da9a9b9eb788c0cf243eb8c9903a3c1c25af556850e67f04d6937065180309d16e1d1a8d191f19e69b47659c55e85544c92072b093fcb060674898da4cbbb991aa52bcbcb7af484d75dc4bfd6b8b6693d4d7127ecffbec2575d0f9fc17dc19d3e990f90596d00eb42818b0801bda5be2f6153c04ac74a554f94a915f76e147fdcbd6d28e022b8918ca4a88e06402c1afcffab1371fc9dd002d2d67ab64a45039cb30e429f6b532f211ab961ddfd1b608d32bae6ecd0ae7a806673d02b07d1fb5741d4721b191cbea2325b32f5919f7ee313c91bf6acf8951d428529bd5f582824e4c365e1b854c991606503126ae79aa98711ece67b61a9ecb3c23e6481d90b806259fd73130d80e4b499131f3980475389ad167a27e21da3a28406fb1765ff8b168ee27303c43b77d9a2b52f2a597f9162fabe51f75574833baf7120dc7c8cd5f519f8cd28b283d3fe2696457009de054bd697897585baa2298c4a4884d61b2756db043930353766b90d124a7b808cfd22861d5201ca4feba2467bbd3be6bb3dfd62dbf5b541d50c93f0fc3ccc6e472c29f00c49e4aae0891728aa80f500001c08b1b46989da08f311fcec4531c01f687de4d1143b2b255688d87ae6a3a0b042c2843bdfe7343f16f7d8452ad472c8964145899b55263267dbc47d445b5edb9ceed7ea56bcf6711d3017c0b7f8b5dfb102b546a7242d8d88c55edc93724b7ff8e6e32792588022e7e8a321f20ba2c1b67a517661d6ec171c504066fe0eb731724b4df700155951855a3b728614562432532ce33a9ce43e219f80d7e1341a28109d0d2c0f0119b8e1af8a5ac069e5dd7c0d1181b780b6e04179703eca454480b0d586b5b77091ddcc030d681bece0dfc04ad7297ab71cf887d131045824bf6bd1946bcd2a41bb8f5e1751025a34d81bf2bba129128955c0bf331dcfc7a90ca2d92d8ab22c604b2111e803c720ba30dffc278ed6d00bdc85f8e551b1967103902652ad5d44089013b04c935590a88c4fd4f9fca8e329c28cdf545abd775088fe04253532ff4534324a076a18d3b61f99d14c068dba0e0633ae22771dac45c45fa43249681703652f61e59aec5b120a0e4ac31c55672ef6a85cb534f1d48717ae659aad3ae37208afc9b6d25ff69a35e7f6140ad1f8bc4590df40b075b0d1030886ef81bc12449c72d3bb4fcad0e958f69cb7d429265ab56e54e508b6c9d23082c506132e98b350658f41efa142708f3759268d96ad7275bf0098e4bb9d6653c3f7cc2da4b0a46639a617562e07ce026128aa551892be641dad96696cc78e2263258465c31231a02bbdb668ef82657a110369e2843067eaf01e3ec8aec23a4c5329f815dee2a2898ca213f3db97a5931df14f01f8ae1e191e33a752799605247eacf3238baf2e1dfc74ced2ef76c61cd23435e292050c02ae5f4a0417355192e3514786c7e98402bf5d3769807339db0344430be5693072a46623cc13a097a40b71433b3d211e2b1020695d679ae9a4ef990eaebf6a1bf6954355019e912451e9b30efb3df39a76f2e5346d58ace1534e13927315e62e65bf6d1d958727c1ac54c0c59f386017c3e4adf00ba1acde14f1eb10b2f3089c5112ddcb0acbf4b51075ac946ad50902374637d8661a4f4abfd59192928d06df0e65ee6077c2116fd393ac41766577b90a146b9aa64443f286bc2b03c8a0177e378eb0ec27ebe8927e8f0c25e867df1255d9decce711e58c71726b4d0be6005de34a8086644a3a8aee899143aed9c4130a33910b6d6e7742aa5fc408db2aeb78daf00c615dc97d6816d1a65313cc58f1c58b359b2f5b615ae3085e67ae965c1bc5b73715a4e9e228e79aa6a7b057f2e4f11f035353273240386a2d7efabb13ec995c72cabd144a85c65615f815066a02ba3434f978946cd5488458699a095634ee8f2f34279132385854663a42bef99d2295ad107fd69e47fd8e792fc4bfdae5bf26dad7800db3890f0e0c66feaf1640d07245985a322b785736e7238dfc51cd5a103aace8c3a7498d7f8de500d3ea5027b1c46cc3ed666fb70d067eca9966b9ccfb0c1ac5411c379c8fdefaeca2e99a83b4a36d2341b74b0a6c86a4067c4efd84f0320c41e74ef6a7998bdc19d0c51675795cd2b3d56d59fc11c63c9b66db62c0e3e7fe412cbb477e99b05de6a7edb2703b7e6ce0b0abfa5ec2cc1783063ef3f0566d17f792da60d74a304e7997bc30b1216c1de3bf0be60bd6b08e84f18b05fda457e5a31179d3c667b61d028324ff6ea12a1a56cb313636c148c7a77f33958d6f527b50f5fcc4a0d1fc618c806255563c98e1e1a8eaf869aec2ef8e00de6960c882938cb07b215cac948f22925a43432924f8dd93c970f05958f80ddd3245001d3722a0909f4c0968c5590bccf89513c7c2476678afc2127f86db034c62302317f52be23429cd6949737c2a5dd7bcb80170bf42ca644183b5a641ba49aa1e72400ddbd7bd258654eba337d49118d61de2d19b15466dcc38b2da403b4b338260e072308c57d565f581d648c6a9afd103e0d7fe618d012d5379de5438df454d1345c7d4a7ad2afa69b802ed4d50f4c64a5c4283b1a8bd05811c29147e6eabef30e1c7972fc906da0ba2af204da9c6caa63081450a4020ca625f0a666716133cf62026e7930acf828c0d343602addb8c3f8c13a6e2a16193d9992c738ba5d1b05215d4f828ae3fc2651dcf0c48bec97000d9121d9af7d5c4209f8d437ee28872a0110a48d33d3a90cf227628215babd331a2a5f2f52f0de7fd8d937a7b40002cd53e691d8a7dda13a62b941e226db514cc72002ed762d6a640736f177a1bb1aa44c9785bb4c97e4c92e36b04111a89e47178c6f50783aecc6801db9fbea0b93c0fac7dd0ef115c843feca11e67f5cd1fb9aa7bc8b4ef0b17bebc8eb6f78ec6246bcc52be115ba35dd3384e221f229964ce822ab93b5d10952079c417ba0f953cb3dea5cc378c77dd368fc8453a88dce3c76d302925916e1260de85e755f42987867a6c1356b58057a919efb582a80b2700a8596eb59dc58565a2d420eb568f81270e4bc7575bb7e36d1944b71ec7d0cfe09ef33d6262768d622baf61a70dd6087c48ca97dd0dbf63fd68f8edfa6d3f681b464b9019881c049b0c0f2c1956484dd79c5ecebbb8c140cc4e8c93db332fd3702293c2442ba3cd457872984d59804edceeeb75075017ca836194c57552fa815aca578de9bee41db02049d0d10b3d47d96356db405d4d26258cfc899f4f25ee00f3cb3822e15c90b3c2297bdfc99289bfdcd109f3566fc5ccbf7e2f6527b6fc58fcb0104c43fd77ba94c4445b6853eb7f93c01ec73855d0301ac9e698de614602dd6f42c7a40fae368e273a8ca29eb235a6228eacb9414c08fd6f1a08f71599f91033840d06c5d563d86c1f59aa65fb0b4349e8e705cf003e4118c393c1e31fb3885a0f5ef7702e6c9955bd796e06446f41625262dc229bf9929453f048e97e8f1c5e790c50df80e1124ce97bd84edd4f35db2abcb1d94e8eb880dfc43e307b3e709c1cc3822bc6c2371485b9054e629a1679aa2637e008488fd44bb56a01a7047226a6838ca15485368224965156e76c8a48cdbc39841ee2786a40a46e60175145006ceac066cf596770bb7c7deccd28e0de8a704a7d08a3cb6a2561bfc62c41ce1deed87edcfc35324428cac89cd537984605579880fff50923f02a833d95994d501cf5c69465ce3dd3438e4ed9ffd7fe446e1c10b9ed8575344f2c8408e258c229d027a6a97c6a08681a5f24c45078d2d487196ed256e623836486bab0387cd6b86099a384d24b7883984107d812f7781e2b66391d1f32f079901e62b045fdfd3f9d60713924a766031677d5e1687b1df33587a633e54aa3e1f2fe58bc6d4c06d1c6640c1655f3ccfc4e9fe116c48484d5c3afa7336ad21d79a010e58ee1b814bc68dac6c233927d18077d9c7787a26f8139e670c1978c24584024989b51cb66ea680fba7b18536d1be98172faeaee216aa496e8ae3473786b948b0d31b0e7a2e5b648c5f6fb2b323ba667392dc3a29b6636805ee4e41212428e81d72909048dca8524d6d57f18968cd8dd197d6d489461d6d7317ea51081126a2ef693f65b0f0e0616773002da045c0ecf01d657035db5d35322dc8a7ef510b8def6f952b29688f60141621256f2ef2b79aad94d3a75a8494d17d36ace3e753d357cdc5fa093cef7c19f92febc4274e42b07f71abc64274af5557f37438e4013e6096499d459ec707e9011308ecfb454a6413648669c594095834f9f99a28fb78ab87ab002f781bbbd7f9518732a2cd5c805eaa3bd4662250f01a60041197bc983f11c1c35a83851c50ab9a9bf505e984b01b4b3b57714532430e276998e1cf00671a8546d0d6ad1d9c0f568fea82f35753b1172f3e2af2f4b21976cc4ef6bb70ab7521617c95010dc8c87a12a53ac3389f23aca2f5db94d799ce79f661c41e1708ae2c1cca2611d4642c768c384306b09a85c541f703674d23c32de4a1968c718a5f880129e44d36ff950cff43737f9a074c7714425281ac24c2704d05db1c14082d825e234ef639fea6f5fcc1398cb92452d3344648b8f3b73b6f51f27d887d4d297599654b1f151635529b0ae4471d9ab36a06c34e1ee95933871ea7ee6c0c6944ab9d7f6a81a7cc22c9776c4a8dccb22696a3c23b559cc08354f9106fbcd141ea02d63c965df2a3cfcdb7e8398d0d33b980c225224d7b60634f37de7004d78a530b4ae2fdaabda26d7a3ecda44133e976960a6e469b912d8f91819fcccc00b526e8a63960e60a0841d0d9b9bafc812bb53708b6d5d51656ceee3adf859b38dcd699ff2f232104995a642bf16c5f9e135f5e6c1eb2794634896220461f92f23d256ef92db06f8c3e164a18992998d65fb0177d4fdd6e222b7c2cc6241b7d84622659ddd7cb6935dfc582daa13984e13c1b26881eeb41be47f812f2818c51d505e945e133ab319a2f6e82f8760b4f652b8850b9dbd49e73f37b47a64868932bd8479a6bd268a0d7e23c458ac248671e55630159786851733aba9b5239c7ab55187c4be8859cb43e35f89ecbe80efdacd9cf190b950e7daf2c5134fb34bae7edbb5278b296626b4b0b0e77f1ef8748ffffcd3181eafc6a64970dc87158408a0799a10685beb5a828db8f196429d8e951ec8ab558104bb9c5b564cdc209f83303c9f5f3a93f3f6c33b38b837e9e3e89051c03920b7314cabbb011a2aa76a51c4b7fa0ab9199b537641f0b27a3aa4b4646a98beec959510694a2e7e549dfc840eaeaf955d56f5a8bff91e5fa146114dddb0ff6d450d4fa1139da8a380d2b3bde46849563bd16560f03a7e49c47c38048e8ebb682b318508e63025b3c80223fe4e2d8f91fe8886e90e2e0a44b9bf94994821e37f99966223e8e0cac0ec461eee4c170a0e7040a3581ed718bc870285ebcd6807c9d1a30263a3aa24de1bdb88c67e0a6e30192d3cacba52f0beaf42c4cef244e489a332a0ebd3e7fa9893395e989a666ea808b877e4d3fc3e1be4ff20c7298820d6c367e4e09a523e64cc81db1ee8281f41bd154769e006c98acd34804f50ec29a412e21db69a8e1c14fa5cb6217c902f3c6dca615d9ea31044108e3938044a3db5094868f95a04a4c78b1b6f7a10581a62f09c9f7b2e9c8b53951df3838c51ffce34813bc491ca1ef9aa0333d2e92e82490f0ad4be553bbbbd4731726f819ce4f2f034521c30082b68e36df8dc40b0344ef6dd151b4e08cc9b823a61b484c7556ccc2a12366ee8a0c29e7b1b10c4a3bc062a4e7bcd9597e21669150e5a2999afe72f301d60be236f45363d3ba8d6b984515522c7c412512c89eb125a522c8a6290b28c115fa045ee83ab970246dc438dbe858057494af4816df6e19d7eab0bcb5673089e715751c2cc9ddba0b4d04d7abccf525c44fc074fc29030eca3be5954ff84c8b48a193e85ad408927c4653a70d9d3ed9d84afb82bab6d53068f1c525e775e21b4a44f2301b16266d48f76261dc3588ea4ee6e450de517f31d3a6010d54e2a3a0c8c023d0a5d34012f13b0d011e41a6bee24d9f346a3875b7ee0a55699355e438095f06d69c14b7642cc7158ba8a198b4059fb1abbe204f075ca0ce6e495c0a47895b2102e2b229e82b054f8b0247bd5372c4a6c5c9d220ed0de0e32810016b3a08913881cadd8f3461e88d781ceb16e707e24ae1c14220f8a2c54d766cc1024bf9fde5a2732f0ba43b08470846966c8c313f550016e985c032162127b7c96b3b10f0af0cbf51cc209e180b355c67dc57627de8636d8cc2e14a09e525101048f7cb0055720252b3f74a41d22c982dac63a7f52c977753d76b687bb448ececae725d440e126ff7a4cdce19b408345756c0eb36cb10a6d07947ad2dadf88d1c06e78f4745e3fb5e9a68aeedb34d3c59f8f322281bb27892815489c190f874a0eb5de38a69c7ac086e7cfbf4909528aedf1aa5ba607779256e5d480116a2451247193aaa718d0af322aba4761a2671169dbe7fc1810bd09222a7324412e7a74f3afbe887098afe48b3ca0aecb14b2c23f6368b24929e584ee0cff387a49aaaef45531a9ad1cc16e143cc61df5604c190d74db8d612cc51a5f76306279906850465dbeb6508bd149120f5cdd5c19b1e3eb542d3b280e9d8f36e8975b5dcc1d760d07a4f90cbd79b99b2c7168603823aef625f9524ac5391f6ac7bc55b095c11d72a1f7bc7b05628c2fac0100740d6ad823369554c469617cd2fd8de5965d704715633a6cf2ff5c8e9d26c07c6b9e32eb06c9a45613851aca560a56fdaa5f93380bb1b98f25c9ff3ad7e1f08acb520c1d86208684975372113c9513a02c2755f477c2268f4f20a78ded932d19cece648eece84f50208d76c7186715cea163055a3e176f4c9dc44de5f3bc2f62cf1db50dcb712a146e4f7b3bd119ede157199cb1389e4139a0c635614c966d7d4109f242b76c4a366f80cd1ea0068b216d59ac99430fce1a41b585d196f6e3e5109e86ccc208417fa0a39d6f9f7ef578cf7204628d1979724cbaaebf9ba06b9ec6c1539365e6091cf8b8e081bab6cbd630072709e53b705f5c3fc2e7a6ece46748197cd335aa64fb83961c3e4eb0632ce535592b4472c3e1dbc8b4d76ea3ee4a664eebd1e178c61b6673e45aad933cc8a880753028d28f641d0c2ecdac688322f627ce42e524c5c60da14157c45a338afc7ca3a3e5645fe4f9fd4cfc9c43f733d848582fa7f78a91a1032218b62c17600897ca0bfcf9e64c5f2ad46383103d182ac7570b85f44fd8a8c800cf68df6d24e0dc9d092cff68986b5500dcb8bb8e0ee252739d8e0b244ca4f0d13a15f85ffa2cf2a1c845f9e55a2514569e0795e9026c4794ed33445c37139f5abf03c81603f95a96bed807ac44ec0a5f742a6d717c32940fd344fb0a40e138d1733353a2c1301ee1f440f90c1f9971cb708dbe36b84f62b998304aaf554e062d3634ae512d0f5ef8574288103dd79aa5473dedef010b0270049afbe5e9ac0937ecd52dbaa79b631da3489663a1c28db117b9ae384b459401f1af9da401ac4f309c4e0928733f805a500119ea7c6ab77843a677319d69b02bba2e744f5562e242066c28649e3f575fa230b290585f243d10b8c562728e1d5dbb58382d1a81360a110c5aa40e6213ae112eb6f85b2b24d255c34369c81b32042af28009ef1067ecaca1e1b4bd4ea136e50526a2a22c102f68e25505436b37cd19ddeef25bb27faa1b2181bf602a6e7f350e14b79bacac13b28010275c57b77666d2691066ed89fbda4c720f0437bd97de721150d4bc6940a16342520961c7d0ee33d454b3c1f561375a41ac0f05c0f6ad87a64680f8ae6662e603d68c79dc8a4a8b2944d5f7ff824542d63a5390aa1c94cc7af61255afb1270a8eec03c2beae267ffa909ad123e6f9af58c930480099dc3f703b6a479187eb91f99faff240da3e1012541c7a80a24a33778eca4edf0836adb56b42cbad2beef181f326b197068d342ee213ba199cb3484c592955e278b6cc14e6f218e241a4fdb901741264ad981a83ccb9cf50c2e4531730bfdab42411637a9de7b09cc11a69621008fe9aa20c9c52ff45706f1a6168ad60eaedceeef42f06dc5c73ace822a672ed269262df5fca887e705ae317345faee0ba476d000994b957a33cf2856098b8c9c2deb3fdd399af4a411a11ccdd281157599fcda7b2fddd3b24b14e22b00953628058c828741ae5aec7167f78208d105f8406ad7d4bd4ce4befdb6290e1f387989e3ef7c300173b656f9b0d621c8fc0fdef9ea7b6d4652058e6eadab1e256ba0e9c8a67b44f6a62f0fd06dab5692542f9ab70f13a4bb9955ebdc203dd6d87426d61dc4af0dcb95fa1dbe95c9b8f880f365ca6562ce47a54a7509523810c10d3c7a4979c233983f4ff7a249d394316c0110f28208db2ce9de82026c8d8ae0dd3c858679f4303b1a15cdbe32b12de1b7a00f97ca77bf18bd59adc56cb52e5ca4d8a2bbd4c77f89ea9269c477f42580ee5102e9caf150831df12f554352ae9e4f04134ac22c2f87093bc901c97434019eb53abf102948adaee65a0ab00e2b1394c2f4b409be34a85dbc3de909c32ba9691a5a49445a7b64d8e3b42c4713d64638d2cc4f2a4d84755b21db3326a9099b3aca131121d4e6d97c1942d2ece74758cc36d037b5a6fd4ea3a6cc504300c2c66a765b6a321f05160a1d834f51fae2a3fc7bc8e393e0c59da4024d5e25558c04f9ce5a112f2a310b477f7f48ba069c42e81aae73df4cd3267d69103805b4d6c9ebf73c3ca74c7aff36ffd86370de3a47e2b8c74f1e02191ed2dc62b04551bc024508236bdb1165c9cf1a59b201cbe26d7ac6dfba06347a0e0884f50d5ecc8548b76582015f6e500c924ab2ff3efd0fc9fbd53a673150774ef39e8f04a411cf406a6a1c062eeeecbe839b1f2f79c187a1c39b6f5bfacdc1e0eb8e896b11203818ba3b134014178f1376c818a849ba6dbd861b5672f25a48b965ca35eb42eb0e37b5efab3506632be093a088c966246aa37ecd1023eb8ada8b72793d6861c8a19cc41fae2dd4089ccf427b25c6913dcf5f72a57ac649105c4382300cb03a61f6cf535a264773ea7efde961c9242fe45b01943035b7a85c7b246cfd69af1748a69e512594cc3c77ea1a11479572872b9a8bb50936cae415bf5daf27979635eb9ebc23eded6f1e0cd6c02b725f6aa80513667b100180281659be1facff678aa8ff7757c90bfb0369ac59fbf3b8a20845c357de73e4b37e63705367a69f971355a886666eaf97cd08d7d3d7774806ba6c99c5e5b897b29cb4a4fc87157bf5e899a52623ef45cf59c929e5527896d3d30b4217ba9459dd6b668f5cbdb04202cc671864142b2496bbe77a5ccc70a59c37a07259bbfb56a434e77a47c08396f99e44a96de26ebd7fe536d2b983bb34d30a925b9080f21b5f239bdf4b5bac9aa84b338fad85c95bb357cdb0f426386839c1e2986568a8714433c0c1a6fc060df60dfed6178284d8e606d45f2e3ca0a5bce7c160ec1d961bad436b78b41b8578e0609fb297033fab6f459d292f43631364d3197cc4a9a95b48c0b90a314ca0dbd4a8d3d8070ce8d34b131978348f7e9eca87f6390b519c9e6b8ad0b7edce64eec85bdb362e3ce29a680aa8c9f802acf345a345a2b5575d90835c545ee048231b0e01e2a88b16e6b846fe9ac7b29c16c69033ecec94376e108c6b0761184e55f0a17876cc7c69e21c49cdd1346e59ada77ba5c992936525fc09148eb82462832b9e63f13b8632cb8bab20033da1e38c33c82d55330696960854ccb3cd873b08c799ba6de87274f268d360a5d389bd31b4c69848305e6dc41471ecc43201fc4ff769933f4f6ee66f188e16b56142f385ee558490c368f02e07a6c8b34e5a0e9dc491967bda2c00654c8dbd591b0cf7f84e3a2fcf4204394a2090ce16583cde9d8853f30da192c35e38299b11d8583059fc8a20a00a95caa0e97948e3ed9013c13ed0240434d01229f17b382975f970cb0309484651b6fa76f0262f2e1ed3482622bc172957d28f0e14f37c062dd01e3632df70509cc12f1aac7316366a075330f88d3963c2e3427620e5b95eaba6e8c9349835aa179930f888ae62774ea6808ba663ea8417c61a32d989ecaa112cada305fb53884dbbb8093ff40a43df07070eeda6f43f10538dca3c990cfaefacaab2aa374f39f275017eb9bd5f40c134a22a2820f0c2d5290b85ffebeab0fb0c85848538353ea872fed647888b41b92e34aa3a1812f39d901112dd19a304879ac9d69e3608e9e007877d0818774758a0d6e9fd2c15f89b0917e33b6c68ef87c1ea5c105cc18f3d71762af416308ce25d8ffd923821cce33f40c143237e5f1f33ffb7d4a556d95f7972a00181925a115954410fde0aae6ce557600699fa3050316dad1934da5dfa53bb5f2dc77730ee64ddb8f896077e5e777b90b7a586a06f8eab24774a53c0a2eb5a031734130f27f7c9ea26b99899768b08114b09f0626ed21c8ab815dcb644fb05c80d89a8f5f74fcab844cb597801360119e0d41066215b61020b4512081ba5a9ad92682b4070d566ab0ab0d3368a29e6c1a0ce0c2c6cf4b2b25e193afd3b8f38c55a315db52c2b4cda3cc0e820efa4e186cc8149e6f4ae8b34e0c00556f6dfa81a51d1b2a450a596c4f572c69879620939a9ffadca5acd376006f000d512db7b618761851d52d39c41de465512c6770046a238ee44eab740f4b4e1de2b06e28ec841c94683b678e490dac94dd4fda1dd3ec8c93cbdc25fd3f39c312772ef4500e87e8dcff3c9849d0108fc395e795c5ffba819c657b4bc09ce7a15352026b4ad193ca41346f4f2a7b25256b4ef334b8e25ec6b1493b0dfdc39f1a6256511ec04c3a1818cd8af2dac28b3b5428e6828fbf8b1b2e71071d09789e27c046fcf4da67ec8e54c7cc85d26f5c19b1cad987f3ee62af33ee462e63fc26da6fa74a3628897fca5d19aa8b64d24b165fb2787108efbaf1f30443fc2dcad56627541834a666f44f3d954ff66d77dbf7bd9895db68b6d7c7507a2423db73441e9d892b612f06aa5f5bcd107a9730501f5b29d98e75749eb63d260fccaadc0ae54e8bab58a197da50511d9c5243063f63ffcde15c070b77dde783bec1d5e2cba4c06178ded2d439f33352a5c942706eb0af652d131bb16dc90f97960df7e33f8e8a5c90ccc3ff0b8ea099328115bc21c0f89ad2c9b115b6dec233208504242113bbd0e6329b2f6a44e65365a8c8b1e8d2f92e91f3069cf1b30671823439931ac21c35b30a4a930025db2d511e6c11a014d34bb97776a14e66daa54f3a0a97d2b73f1c59f17b5506c908097128e60025a0237d5ea1109f12a874c96fac8b943490c457cb2ec59c062f6d61b488e73e34598ba639c21ba4be6eedc0087cc769238cc9728bd3e149149b3c28acd2822a66245efc0a230a50a1aecb03f74fe13a8dd135c708e284dfbed0bd8cb1792bf98ec6fe708115f16e5592a102dc3b68b62766346078d2ab0c85de378f8b426c98f038b38d615275dd7320e76e4e0af52413d7d8161af8c838dd881a56486f97c3cdace709b82657612cba4b63409babfe90961d7b0beba01202180ba7096cac9cd8e5e105f4fa66f7074a4b13025d98aa9bd0c7ff42bf92988a8bd78db0045e2313fb6563e9358bd005a9c524981a5884a009dc9e9e66a89fbec884aa7513c162a3f1b0201612993f621a7dabe57a0fd167e4f75264c940fabe0bb9160a002fb7506537d0dc59ae96917c320da981263cd5b2ecdb8251ebb402332a308e58a49dc94e0af5d79855142008264919049aa7b1ade62cc18d4af2687c2f6c7ea63210ab3c0d19cfc132b42d261c377a23008d64dee4aeec096d8d42cfee951844414e66b5841418c2096bacb6fb84fe2b1e49a0d26a050048bccd08df64aeafd210a73d121bb914b95543b19d15da5306850faf2c261843e20989ff1f296238fed6fcd066f2b8d83346174c7ba412cae2fb42b68146b08735a57ac3363d7329155917aa1284589492dad2109f7bb3b1af755d038005562090a74276b5d371d25a24edb85209e5bab6b26681a0fba4f67d364eccde63cc5bfb6d0d3869bfef9508427ed3801d49644796f5e0aa54db567dd996413a3a473ccd292eab834ea2a9b88b2461052e65d3f3208321a93c43d4c4a6035d690f488eb2a5893dd541f306b8df3b3b59598a64819ae08310e7fe35c639f39b211dbb722c56fbec2fe45eae663b20b73db2f4fba4c2bd5dd3076f71483ddb015b2a13bb5f33f268c8961f8c9f68e31c40658ffbc843abcbcc007ac026814c0104f41bf016471199d602316daece47131e3c99b1885b0179807676a835a505ecf56e242c49957ab0621a27e698602a01101d81ec43a1c33370fa0ee835024155995c18f17241a7cd87a5f36a90426f9c312bab0667ab6acb6d09f8be7bc8f9814bd3780815f737c31034f39abcd9a0b74351d3d471e1dce002369f847f52087110ba15bb64ea305d9bd7424c6e2d82f83fd7ebbf4de9e5d881dde2d44d340a5651dab4d3e18cec9470b06215d9656d52dff1fff4dd47b37ce5755689ad4c1fbcea1c07c9e6918e30360252611b67542887a5210184703701ac6e871a25b448a370ddc87d5727107740073801c70e26c81d40a02d5f7ac067e189c6f831093db6420052c051a8e2bfc745a9a20f50fd7f64e3c3a24b083a0ef3f3e1c7daa94e8977ed60ec44793e809864dccf72ae956821d878e0e50d8396bb3c9026575d6c1424408bc0594fb3f2806b7268e527e640c428478504ac9888df2e5d34efbfc540648cdcb26bd092d45068c7cc01b1593c71f37541af79c2a29dbae78048efa32d82bcbbd4a88500ca284bcda1dc77ad32fdacd8d136f242b394041475db65c30fbf9b7d66fca1472b82ece2a5db960aa15e77afeadfe9c2c8579cbc195dc540d8ae0151c801ff45eb616b42f0c01367c5ee8861af0b81813149501c84d6385585c8a57f14d9393214f7c728626e1caeeb5f8f37e640b13762a89672721f3a976ba0a82b66634f0b2a9b0f31f334bd1565f9ddf3d570a336d1292800482e53cada6a0301fb8cc5250b761a266d0e25e6a163eed183a6869315d89361c51cffba16fe00154c8e431ade145d2cfe3104da08570b55cdf92144012ce1f24bbec4d830a2fac4a680eb159f1b1e1e6d2122f155c67383340af8239c34bca7339f4050bc715f85e21e9e284941ff4cf84c83c057d0e6edc3f3fe036739fe336b37d40d36163f3a68377f84e0795626aaef66c8db55b2aa674363c78c3deb652bfaaab1e6fb0cefcb68ee041e8d548a5018a76932db83a35b062f2622b8933d2882914426035a33b82580a021a4a098bba48542ae60a40c857e4d574250e91662e1ab3390c310bc69c12929ee9d93c400ae4deaeb79f0d9f13e586a0f0ec8e16481c234313dbf59c54c65f32b91ee5850700ec3c56a00d0ffc2a357943b0e6fd64a814d4e048ccd5caebda8c2a2093afc736a6861e0191e07b5bf6f3a69245f85ac771bc51102e270e352bec966871107970b4990605e7f80cd52e4cd113d63020af8c221811a5c36d2bf92737579f938a21b6d19aac3b99b950e76bbd79e6690dcbdb88daaa718ffb0e1233c03be1f46f39f4f2cbce3595c6a8d524f147815a1bba19a8079e93d6b260fd4e7482c399ce01b09943474be76d817a040173bc58fbd04e953aa6c681522f65f71b0e1045f32ba427c6f2a5cfbac8be9257232677562348d7b95b4e47d249e2c26d1479f51157d12842886a8cf73b19af0b59ede4fb5d84f9ba2d8cd527e7c1f67a2d2d6b31251362820095ffa1ab43dc42b7f2924aed2486e79b458c531919a4114f8409291efa4a95506d43a6e6d7056c5fd19bfd3830ebc4f44361f822cedad515772f4cb988af1f67885c884b46c1895b1fc74300ecf976d03f5d9c0325792c5486b33c9df2e788d2cdb0aca84bd298d68561af153a80024812c4c7ad9c4a454bc3274813e00871c2395aba80a30a795a8e29d26ac74e316418ca7023bf9f19c5ef83c6563b0503bc7915c18bbe2659247982b189e483efa3dd871de72d54651935665a244bf0c71d8c4c8ce0d9a8e9437a289f16f9ecfcf325562fed41f0509e7cb49f2991bc9252ef7fbde636b4b12844853498f9e742b8c7ca3771ea0c3b22bd9162b9dd001c75aac12165fbe0e708ac1b2650d7e3f6dbd6a476b5f403524e50c73e983b4fdb043e2145b5285adfed246331358dd911f03689722d53efd43201b877c7efc654c88daff28101db714c0cb2ba179807db23e414f28982ad932accf6a51d889f07e6cf0f91c21b6470aeb5ec3e33c0bb1c0f4ca4b23adca4d6340a735fa65e08c325d8da56935c36cf1c8c7a80a8ec48efd7c047bac754c7f33de0c4b41420d926f66986f61b62c13026f54338f2ad58e48042cc81f745429af1ee27904f4dc80d75d7ddf96e4e873f670db6e6751dbb8881b55ff5a33b8dbcb31db2c14efc55a6689f19a203f993577fd9abd5ec4965a7d031957d1678f1259bc1125afffea8d3d62f11c40ddb971adbc19cbd7f70bd119ec6d74553d43abf7765f84db86b45760728319c1ba1de43947bf16175b96a06a413d944b9d9d9416591d1928a536323e12392ec9849b33c650184c525055075f77cb8ac246e1027787f75feb5ccab593648693607fdb6101c54a017fd7045366d545eb83538818806836e6d7fd3d62aa478095c4104605897f9cbde23bccb424427a6b0ce23845c2623a5964b54b1faadffa3489626662028bd30c4ff60bf04abd5f3d82161d3393f7c14e03935373de9b739cbb079e1ff05c590d514a1f67f7d290c9b1765358c00a499a8d12069a2adbd1523a57c6f71d24bb866a2202aec890d90ed57b69b4b5fbce761a66f34adfcd6878cc524e9482f40705bb1f4ecff874bb81928495c8c4badc9191532adf7353262e7448299eb2763b907f45e46cdb3e1c9e95caa515d8b4a028dc3120be741628b003c06febdbad41f77bd78949dcc6c128a66d481f1958493803e2c8efc89f2076ed019817c29d5558c51683e50e9b4bfef31ccf6cfe13dea9d26ca8de17b888752a3ee6c3991bc3f5982afea4b1a24bbcf7b6adf0a412bc3732f93165f18f07aff27c0d9f97dc721062164f3775441c766d7a9efd06c184fefaae5f292af4c411ceb77b6aa4f154b064acd11e4e562c9705cd4a890c58812228fa6056bb5425fc5abfef9a938d61adb5596a16027acd90ea3f0404e1042340f7d61e0b03ac87b142f12ad47b3ced45b4a9901bc40b1298bede10db9f1e9e3ff133b4457ca9b3f6e7094ae9e3ef4f6202f9945e6cb1bd231e1b37b67bd0c2d597c72d601fd02465ad6b7c6d3ce08b34fcf64c7e828b1488184e061b3ecfcdd0e61f90cfb454bcce9de53338deb430a245a68dd9ab1998730ea61f0f44abc52cb4d755900229b7e29ad6ca500d78e791172c38730961cbbbe3085d2f321ec7056470de6fe3961a240e9c29c81acf61a63361b786d418dd7932ef7317828162c40d415fcfe6ceef11c62978304109733c293d4444e88244e2ca5062657067f53e44fa46419843040c9012b0eb961935a4203cf45413e8465254600f930f66b1224023a5dd1d63e09d774f63cb56c65214fab07f258175bff3883d27c834663bb74ccf1ee438265d1979b5aaf758d82a248718bf29b6c45cd135f9f53b14cd0c89c001c853968e5435fb5f1f82f39a8368bd94dfce18e1930ab3c5ecd8fa77873285a3af5b6ef84783075a2105a4068fae0193be861a2a8aa0af7a6413ab998748b58f8b8f49937a488c7914c1c97e68265489d663cb892de96ee36747e7265852d4419fa271e48ecd431bc94c9044cb61230b3512eaf3b254a2049abd0b461f2dacb089d2916212505f48881858bb8a6c4794568cee8ef45712d7ed6119d874df26d040280147b6b4460de429a46fea2c9635a50b6035073b819439b6cfea371d9090ca7ae3f467573c47ca3674bf8fe522603aeefc272f5244e9cf535701e630d11a1805fbde7b69a7247cd2b4e95d90bbcb4e00ac3b7fce4f5ce3089779514b1cffc450d41f6e9f1cc9a35c5431613c950fd8d0cc1dc7020fa8bb2b6298db204c0baadc670987fedaf24e84032929d88349adf8d3f683b8f1f96134b71d087f7a161e68fc4a362e22a09c4ea58226ee90f5db353124b6af9b3ae5e5432539e50a04e8ac7f15ac31a21b92fb33cfaaf6702d1b37f8e76f956b38acd84d1dfdcb56d677282edc0a14ccf20d4d6374d95d1f2a55ce4899c78805e4b67984790f31441d7acefc4add13e691056b998e6cb0eda0216e059faa178cb551f3b0983d1052422fa134b18e7fba1266417a44013de03c525470b80a30067b5694bc70e8d13a42181494b3aed5c7ffb7522328aaa63b17f104f712a6fb2332529f29e2b8fd7526484f31f40444782427d085733b1e514f42f3eb356f11c07880a5088f2e7798e57d142ce38a377b9c294a75e2cd81da277431e60c52fade5a3c03c8575a6b3aff85ca434f6490d6759d32ebe1761694ea850fa886a4b0aafe231b09bc8bf98e1f10b6d135cf585644a04f68fe8e6c9766547b8087a61d92cf78100c58c7576ac971268f6410bec2301fd3654e35babf4227605841968a0eb3e7c9493a3ad74dbd764c61f56bb521f8dbf846263c2875f894ad9a138bcdaf57ef99e4d0e81549d2d96fbf1cbfb5169e882bf64bb30e96b9e14cd8060fffc01739352c24789b6760c53198a707a4b63013265148bdb57c0eecc7967395ca9afbdb372280441ea36a12a59b7ef1c2a529b52f088e52fe54c67fd11fc907a4f9d7b4050c05e355f97ed8c422676cd7102ca1401ea6d7b670d54b6c37f773bd0389ba6cc1a0391368c090d4358316948ecbaab313857913cf61695bec62b9407449662b2eef0260694659709c80ac68ebedbd5744e142059108c5ee73a3dd0f8c62f3eba73a052ea2037b9193f4c194721353492cb11649dbb88aced12fb6811a796c0295989789658c7157457628f6dae259f8dde2a6151705a3475b1c38bdf402459df511bf0ddd0e88e935df4be13db235700e6bd206610b322a6259b3954665495d4421496e67dd3eb708d51eba3751b41220e4f5d65d73b44ae95631848ad5a485881d96a4cfabbde09b51d291e1c73bb2a980894742f940d3aa52dc82c016bc060a2dd4b82291ee1fba106bf02ae305e0124ef723545660fd093a1cdbdeab90f64016d7b05ccee66841a82d9edab9e38b9c9a864cfd4d2ed96debe8c88f9cdc35dcc8048b3cc4eeec5d970dc069e0cb60dbe7a6ce8b8c090b21e5de56defe0a4b2b8097c3e084059faae006a8d12bdeeff09473879657e13e8001f181b91452774b5f134cce3372dd2e288d161623192ad972b847b51480f0ce356f1c1e3871193ed7f4b7070209b88641ac6335dd1d010677f577c7ba3b1e48446161baf20c741ca4161a2a422677df6a90e94abaeb36ad63e7ae6de9623bb3743689b6fa5eba49f4626f7d08e6197409ef0768357babe470f194991096a3312dabecc6a33ecfcc8f024f1dbb92709fb4d7ca4abc4cbf5306999702ab19bac6f660319c5c5b5606a60d607575abc8c2f119922b5ec63fa495c125152c6eebe097d7aca11662549afb59107cf08fe0c44fac8255122ebfec43a6f3390ed638c0923edd28aa64754d88ae0bb50fb3fffd930eea59bf6e3114f5dae76f477441a03f9901e752b1989d155f760a32fd45abc38170f92504625edb96cc7130e7080a3a335a88ea907278e991fd6a294371cae8eee422afda0e8260be24df1ec8cf2f983ffb011eec3d5ad4c4eafd394e29ea3fb2b812d834fd94d60f4d650aaf01d685c1f7a9033cb8b3a4c2bd082e0ca03cea48d1b2ffabddf4daeab64005d4411ca42aa07131dc21473a1d04ebd028f8311d0dd23d5f3f059c38b9bed096237c3f28ef0138198c883609cd119c6beaffffd240b10cec4c649bcd926850cd5e898eb2fb59d85d09a45d6cdd7cb3c5a408367cf403e1a282aff326512ff63dd6dcaaf2efa1ce8206c29acddae5c859353731485559de0c8cb95310248b9458a058a41ad35868bcaca84f8c8ce14d8f94bb4efd35ca393f8ca14afcfc4ae131b67c865dc2624272bf6bf3c0be94a5cc1a3b415fe44557285b1cdf16ec880b9e5cdfe143cd600b943717b66accb141cdb13150d4aa60334405b4c13e99d93f870c558c42b98b7ddf6846f8340a5e28e28dea5955c942101250bf92b1d6ad0a9f0032d9d5c218194e254e65390a9a21ee0a4d41b149caf7bd04d9c3d7b4e4005c21bd547a3aec2a83a4cc14f40bbbf59a92c6976b2f5844849e67f69719ba85d0daa3feca025ea6004e8aaf5d2a620db795a78209847a48402275cf8a051ce1596c646192fbc1ba037484db1c07bf66856d2e60ab2c90fc21a21db68ad2f4cf556f5739a8bb05f9b56da730c511aac7cd06e7b3320555da689f687fd18b95789036b2d7f7d51371a8271759bebfee0f265030d919941d628469210ed2a832dd19638020529cd4abb3108a8c9b9acd6b07deb17aad43e4ec6b406b8e32728c2aa5fdc170b59100a025d436d5c5072f3cd35830c00406ace5e3bc078b4e0687e5372e2ba49ce8328fa6278a144077ac614b7bd45c47eb86223589644c98168d5b25ecdcdf13c7f0b14f74a955395d3d82fa38bf0311169369d266517a3e98d650489ad6bd9c667629bfa0d9ccdfcf2b95238a7c59c0afb387263fd9d14191f40f86e374a6d895fde2d31a246119977ad4fb702df90a9ab82b60567c4a04c68fb0f983a502f1592115a9b78624be48985fb394e0e361cb1592ec302a0f494c6b564fd607a1348bba18c116f8d0fc6a477f874454343d26c7ff462895e202a624125aa7c28e90444414103194483530ad9d925deac67a76042bd3b7de5990f31eac0990f8f0f24ca48bb733183b98e8d83ae86a76a6c2da24296eaa188b3fec61422dc31cc8b925c2362dba3d74f3bd1e12884f8249ca4835e952f04f86f33ccd785846a2f8d1e8c4ec1857895b03a316839ad876033a42379d86fb1a8f9e68613dad5e1a59257be1cc1c2efd9f633ca9a4781a40a24f07b0585e3deb5f27cfa2782518088fdf0bffa3def14c91874860c4534d7f31a8cdad813afa8b3ba0fb573bafb03780b57d0cf8aa64ebcd67b4d41c1ef3e64c49b27222b85eb625117222816fc7098b3e8ce2c6eda12445c8f7eb830cff214e100879f032fda0df4a765c5d8641efda700e661837ed8fb077661380262b979db2d20fc551d46982dff7ab5390b8957418d78197021c8e37449b797adbf8d8d01ad56f1818b4bea5d0f2c3198bfd9733d824d4c5657a671d38e00450a4669d140ba1615b790f5ace2630178d844420e27ae9f019a0de82168ebe1e2d46e27b23f7d8ea8bc9aabcccbefc895ebcb99a4ec2e2e78514a226ab925674d8fed04fdc9d5b788c6813e22e3cf2b3946e45a8aed5d2b78b960882b8a6b9d85653ed90ec03d45e1b63410343646b7c49267edf792661ed256b9c94e31033db51c34cb95946660e733907c911723ff707318a4e7c7a28e407b6d7009d930c8f078ef27b5423a918340ca17b0280f69f5098d4166440081d266ae86e0be8d644aa972d4351b9ff4645772137911fa561e6238170e1444845f8082058de2443090bb194700499876eb0200d7935070a281fbdfd6638686e473c9fdc2897189deb4d1aacec62a7d0c537dc5fa8756a2f42933e755871e18d53d30c21ce4340fed2a824e835db14a613417e0a171282321552ad5c46e76c373a1aa84dff76d292a290ed58bd3a6b44159c1dfc8b39cb2b33868ff8902f13fce54049e747380520333529a7756192fa87e7fd1871676f69c182eb584a469506917b9e79cf2beaea58afd102c971565668714f7f8db89af149da3df32865371a5b39b9746280da7769270083bd2d95578b7d48066219a45a0fb27d94743e295e42ea5ec6e863844f33dd6d0d0bbe26622a0a143b1572ab0e38ae5fe2c508856a5e1c509a2779038aef7b2a834a80fc2c12006552cd43db854a33c521d2f5580c345042f6cdd0d6a2ec0aa3c75889f41133f679c8d811dd7b41138c2a8acbdef9a37295bbc428636f40f8f3f095027430d9760572b625da5f87632932ee6b26b934b62c42e91fc9b251f649469078a7d0bf2f30ce907510b8161e47ef6d67ad501a5c8beb913ae61b22e5176a938dfd5b91f7c7e61415de939173360f3ff3b983e41ecbbc12e19448c139fe74951f251f3170cd12c3a03660cb125443c7f15b13a33e2368fd8789104bf5f588c07879ae38af3b4e6e7241a138dd52e2849a70d31d0ec18f6a6a4d8277123771e5ff7333f779856f9d1b0cf5bed811b60b5ffe0b0516589a0b7b8d9ce3beff8b532bed89fc8c1027ec78918b34a049a449e3095cdfa372ff2652380bd74f4aff3f62c7def36701dfdcc50b163fef3318279fd0b9d0585458282dbfc86facddb81beeef9e967a71526336137cc080c986c290c03e80b5990189f1941289cbeffb7f164de9809039ffa9a529bee17158eeecd7d1a567a1eca820b95037034ea43535755d37f4a3b49ff225e032c9203b27b85f926fa4dbcef1308e2965ccf31a1e059eb9638f2d5d9b9c85fd25991fb043ff8a86ddb53a2bbb1c720bbbb8271ff0864f59b847dcbd9213c4e2c07c374e55479b6411164483368a435f3f5fb49e536565fa450d5531a64c584d25e5270b90a7b2672a763a5484c24600e95d9a470981f8b94a2d194b814b44b2cf4305d9aa1aa1f54eb14169baef42972f1f84493f3208b656177beae44c05b4d9307c7350ccf74b193bb37ae51ead34b379fe6d466baca6016047924bf82fe842e71a15a85075677a18816f3a1665dcb4b22827e9ef0b1f7947fef436a7649fd812325e4ab4ae60729652390f2f94c300541c42450e25027d63ca98743e13b2f9a4660dafefaddd96c583eb8ea479c59f2d846d478d7d3baf4ac599a2cc336b8ec86c2302842a6fb940b60c1a75e03d52db39e0ddaa0d4449809c388f87a5c8989f663244aea20fb7747830855560ab283d2fc8ced7d5cf1f297c442f41a65dc5979235814381a80151125855f5c203eb414d53eacc7139909203004ee5758b1ffb1a5d54dec6db27859632746793906a65bbcd93cd92d43d9e98a0b58697847b62d3762b5d9bc7ae4142841d12eb71ccc442ae7064e5eda4831f9075e936bf7808f0f9344db9af8b22ca0fe1d1243900a181f0027d83bf9c68280e8f3be21a70fbd3bd6451802d424bb9ed00b0120b717e651812d8f892e83c0d107c9d1157bcb92d1f9442bfb7b28064d36c99e59f50fe39e92a73780a78a05a27db9025e8d225d002b5aae0c27a3413b4d10038468fd8ae4571604382d11acac37fca45c6bd58aea190a630d3100482c1d527e720163924b446f7e655a71a918f7b0e3239a7fa24890352467f122503ede81abb653d1a27690d2638227aff8448f9f12b86bb8e7e2865a4a1fb794316aa87f63345bd1c2b000170e5f49853f47f02ac6ba7945429f972effef24aa52a15392bdd8a9f7c4cd579792ba309a813f33aaa4b18ea600d992f6cff9aba80e2dc880059d5169c2377956c8cb54caddcefa8987d2011b3992e2f83240f43d996db3af5b68c51e55dec2e8adf5d65985d931b863d0cd95e22100de63da5ac34184cce769f8da1b86f6482dbd3790740442902585ed3250d943ef711854e2e7684ac1990c636fed787a4a70e1fc0812c6aad5950689cbcc03da40a6206bdd4f5185d54c375e5dfcb334378e0cf5e1b3bf21b5687d446659afcf564881062f9cf308faa0615465ee89530111c125511858ac900cc2d6cf60220145ed4c183029e692ee82aed28ea25f38f2df3016117fa5449356c052ac1628ef6f624794ac2aba9d5d47acb8053f73c644fe92c4f48cd9b255f344d9ff035873bc88ce74b212c836f9f814e30e4f60ed95149b101f15ae4b5b9aefa23a43c898d7c6f24aaf339a910c7a9a7e4de8469d1b14301d695914208a06c952d28d288b42d0b02ba1f749f765f0f679221942c663cc5defb20ff2bbb563f3940a21ef9481bb461cecc92e2ca91e03754e4cc9e42822baab5fa9b4b87a8b65c88e66f1d1118970588b91c08b610f4d1cb9cc49a75e8943c689660eca80dba9a1a20c3aa983326e9c0a4ab498c125f6089b2d1a47810d0850d84d3b4ec9a14f16c90eb24ecb1d6ba9b52a056ed36126942722b5a5ade2759f32f621e3db47a0fb48e37d98be23da4961a226ec1f1216b34db03b08f3f8e43e0be31dcc5510a785866c0772a9921bf9badbc6d91e942dfcaa594d41bc73aff114a942791b223054fcb7162e6ddd0aeec6e0af9d8a8c66172ac142a3703ead1be1207387ed361494148021fe1edb1fe91bccdc4340cd748d43038d8a395b77ee80ca6f54c48d51aef4c3ce2b1a784dd12ae1eb78089a708eccf20cc87d736746cdb3f25362d0787ed650d39104cad40088887348a174ce4ea84438164426ce70f7e7bf4502b3c2f0e5547a589900bf1d3a74c3eca8059f2515855ef6007a2935159585ed9abed5bf59321fc83c7c9d67d337f1b8015e89e607e18dbd5674a74e240c8714970e1fd2e7d36ccd548a26913be2b8ced4b86d48c9bb4f49b68d3e0e045c26a05806155323fb280ff9cbd4e189afd22f18a87018ebc583404d2e822c96686acedf0415e82b8ade856d8b56f6a299b8b20ed10a42bebbe9efe3be09fb04ab53f8c65829bd898100f4f718a310e6bf8679f1a5fc21845ae67d05e3840abeb5efb7d1b5d340362684d8b0590a06ff87234ef2cae051dbabee37d66a2e2c390ad8d6e4ae200f29306d20aab153673b80cb4a2bb6eb0ef6e56ae2e14c51b8d5c33a7261f2688948710aa487925935a3a01a89a3292406170e4d16a25815e4e90337ecb211296d1bce6e5e68782eb5a8d0588783d97f6584ba04d923f703e1f0ae5fc4228bb090c560054ada59ca191d0ce90a92b5c6bb62f8628f6cd1177248229f2ab5daa7a6c75676528d3a5a12307194630b0616f4c6fa67f70f19c156ac1e2e3d8ab3cfbe503586f66743edfca402da711ea5ea94b40c5d4a9a80ae6027fb20d20e52ad740d9395e2e65b3f00b027b77312435b22dcf183365712dbf215e2be5223b4bdaf6b3e23f7426cdf120574456fe05af635e994221fde73272b26ce872c3f6041787978cada3c4db8691994f104b8a55d4ad7d86e880be6bd530f6e9da2fe9340d8ed763345a1396165cc9dcdba48e0e62288d5a2b97b2b551d1fcd5659135c40fc52eb20fd360d244b653895ae164ce8d8905c33441e94268016858fdb368a42b9faa8ea03174d6d4f4864e6809570c6ead5630d48ce540b895d8d32409aab36e3bc04a5d59fc5dcdf7fc1c21df3b3b4e7120c624ed386ee8b398aba49763ae73e4052d45d86517862867158e249c26053a7fbe42d69f4c1c964ad80000b399681f4a8bd2b6cabebb2f7a8e0073c887c10f17977dada52f71705ad49faa2d4fad78416d9869d60f82d1848b34f986c086e19ac4db68159e5ee4e9fe3910a575c455c9bb2ef0017a853ed072c6ec110b383d7c4f4ad1be18027e45220c335a1c3e1442d1d15f7576231a94a99878e240f852fc44128ea935884875ef9a2048f9d44b24141d8b9663d40d4f9eef098732153f88150a7787776fb790e82ac9de75f4654668b8dc4a3953f7b89191d567ad2c8bc20636720d3bf08603e407f8d8fe899c746395855a674221e421915d6f0dcae357238b1932703ab3c9703782eb7a3716d4a2bcdc7bf49ba40d609df81b6870bbdaa8d26d99a6f4ea540b4323fdca7ebd58c0872b552eefffa15becd87de9b10cc5b40e5fb0dfadb875ccecc47b9cce40f7203d9d7fe00b3af8e58127be8b32b38b939887e597a14c62631f65a5e436e582ffc0de36f2444afc01b4cf24cbbe152e197e8d37d1352b6c2b3f506c4f45ad0634a8f905e80eb3da9c2ef9ff00518bee497f026927457eb1500f06562f743bb317feebde9b0b7c2f43001fe4d85af85f0b93d696e58c70fd7709b2ba82b0dc74ac58d088417c71b60f941c43678e359fc50b1982b7cc62eb2df433fa1a37be3783ca0ffde8438af9b97f6122c3e15f0b70996b2e8fca7bb49751c1c8827908a8bde709160a313cdc9f245553fa4d3deaea24e4600e54c039755615746c16442009375208794607945cc131b37e2eae9c0d48aac7de1522a820e7bc7491fce8041f1caa313a159e44d6411bb1b4d7038011ccd63570d1bd8072c7305ee6dc49c0d54205e514d3a2f1fcd29f31c18a523c63a64edf0716abe192478f16932127a64e22a308b4bed0f474d8a10aa0005760ae5513ad7ce77b3d3ff30add3a932219646b1372b6a2d6c6a66d6d65a42082184ecbdb7dc3b6c0dce0d7a0d1afeb09831a952c2b073e1b61be991e923b7e89e98b75f20864ebf3dcbfe859ee10ff220114121510aebf513c734e8d28b30087f9454e3257ba9981ef42f745008c7f4a4393e03d1884e09bad94f26875eb20c6720ce883c79c319883336ecdb95df2e0e9bf4d985397e8bf7d2c7ec2cfd61f2dabd267e06a21130439e4c4594d9e646830da27c72a6d2de991142087d7ea61decd73eedd33f9da35751251ae9557ceb681dbda37774155dc5165b1c39c2073e5891a357f11ce8557c9122438608110204081658fcf871c5155554913f2cc71d7147d41175c40fcb478ef0810f0c681505f42aaaa0f42a7e1629326448fc07851c71040d1a31629898943eaeabb05f5b61859cb976d42970c41f3976d8f0b8a2d2885da0a917238687d25e9692e251112c02f498d2e7c060b186d0c391bbf7a7a0188afa73a58f7d2b70851e74630edd15f4e229701910c8f42894b5dd4d6095e3bb0361ecd908b8376b8a8c82e3119f461ce4f662a4f415694410d0c814a34cf99c0cc806513608a1857006e6803de8c00db1b144d23fcd4ae14823c717ff62e408c4498ea61cbb1cff717925a76effb437afbaedf3059b9a2517b7e68b17f87b91b7931b73b7a40a867dd685ced69c8b7b82617d0522199e21c32056e8c9b1b35eb0f2f09f255d96ce05a5633f781412303b09896d44fa9792e12d5141655974780c1661720843237f2ff67ded107f3034327cf3705de03102f167bfbd71f7a02687d1b0a2688263e99ff7a5ac7c08c8f31acc4a4e7d762ea9976efbf491f666297636e0e872c7eea78aa791618dd0b16b5715311221d8914c3a6f8f37c35f8c183b24ec639b9cc4046612ccaa3b730a755f4e303472e9d8ed25b2d31e8e6c7afbfc98ae4afbccda614b4732696f721be9a4b737513ff643e5197beef610bd74db48ab886e3f2f6a1ea9325b668e8d82ef6e5fd1dd5a83375110f74e8cced1344dc49472b0dbe17f264e9cad9685f3734a9b2662d6e41963f4893d445245842709c68e9c7d4bae66ec9df6e6777213d9c2c60f69225da45950c47791f676b4377b27cf776b6a58e3d8b9c01ea2ff341153747b916874d28b762da6fb76f4bea33ed2ab29b2b87dda9b3304ea56d46284321e7f70dfb437fb8a1debe3d3ad3c73cc378f66cd928c8345f1a022522aa44cbc4e62705363c423ed49085b4d04fce482fda24fe67a501fa94271e4912b49a3c5070372bdbc1f8d2c7b9a7595f28502faf509557a46aee02fec57d6b385cde0217cb645b3a0e87f3183e0af5f187bcfc00b03595e79785d17c85f0c1af4f1c84c6e9977669ff6e0177d6a64cc2142feda26c39e91120ef68b3c39074ddf5079ad41c499a40ee1e386637e62948c267343e69aba24f3935e8b34628d527a96192f8aa567e732b54bf27a4d4c52a9d4492e3b179254b5b165f9c57c72088b38fda391bf79ed8be921a211da3cdd1ef719eef1cf8be11737052faee4e890b92385b44ecc1a9ef39a8659324dfb975dcb7eca3e49ae9d5e086568f8a391bfee1aea24f724a8d3fd68e4ab714ccf18f14b93d0a3fed1c873844fff327cc2430c118dc0f04b3cc9af77a704c9058a728838636a43c419da4daeddd437ca995c98af67b7c7ffe2e6f8cccccc4c4b0a9e9041ec6a5c9f1886bdba6037e8a322bfc052c7aee82425957aec5c521bc9fda6c8249dabad98fe7a2439bd30c3ae4d0cc36432c91591548f56d368341d29d1595a0b28d0b0a0164fd0a1d9685564a96907911c45f2d99de4c6acd5a04e82bf92a740dfe9279ff83379a9d7be4dfc4ded35fe7a8d1852d117703ad68051105b4fb36f13abb0cf5f2a0cdb80d76b7ce97496d6eea76938e6aad32ffc723a865f40d764c531329f40177d764a906c8070098e911afe4ef034c13132a3deef6e09d412a80d753f2a32c9e7b779b549423f4124f49a0932c94948343cf1d78f919904e3ee7d79359af6a4cbe824b77beab656d3ac0e8fae4fdcdf48ae56a3d190fcd368523aced223d2e8f17e53c43c7a91dd893a6c0fc3b41b3f9940e11e2f6edb3bc57cfa8bd349f4d1eb28dad3fb325f6bfd8b7f336bff370ff0e2c72f2eec9586913ee7fcbc5ffdb569df14362eace5796cd2878e41913fd1ab68d6d1e82c723473e87e1e28692c98f386b950b998739248988649f79b99749409a7719466afb1de2cbb21f31551729c53d49f329b1ebb1aa6df8826d3bc097fd72706014a7e895ce0c905c8f00a4998c9db06b913762462a6475d1ed59e94320514ad4a09d1cbe8228c6a8f3bccdd3141c2a5f6b873ed71303172e57696a858d3d11ea7d1703897c3a2bd1c0e088732694f725cc85a910c6cad55b427ab4d7bb2221173569252995c565c3cda9336ed4191b5cf4bb51b33f3dcd19e24e1f0a5839290cc8be60676441a81aed1c022ae2cafe9685667f9aec29668a48a6c4dfc61df45237974dc5a5377a46e2db9b58aae76b70a694fb6e44a765f5bc132d9922a1a8d45fd9e375bd9d468b060677605ab69937237ed498a650f963ced7140ac8643aff7eb2d72e9cab9aee0868442770b1f4d1ad130f7436a725e9841dd9d59fb91977c909aa6699a462357726ad84be16e4bcd9ae78e6a163dc72357f2d8cc28f94bd3b0e4891d87a3356142a5c4d45e3114d75f5419cf56b3ed684f3ec3361dedc9fb74cd14b4903c53f2548dc646a39934595e9463d204d829d25e4bd0e5f3f38e9756b0dfe5d32c7849933bc71c45c474e40863ca3cec5f44e2b1cf760fecf7a3c022b61c8f028be81829f65175f05d44724c9172e26f45f612f0f3d2b15de9202bad9775d639eb8c6098b2592a25e4e15536fa1273edcd31d8ef530910c82c437f94665d5a58c811b15e7bf3879c18ac4d514168462547867d4c0cabb3565ae9944c605e9db1b3316777579704cc54898a63ccd96ec0a2c96b4f32d44a278ac99b95447b524a4f015c184c9ad564b8838da7b8c34cf60405c4a494628861731eb687414cd2679811767e30b41e487bb57e13a3af54ceb987dee9c738e58c32c6f89eed0981478e18ec545d5769aa8e8a5381d41db1de542cb0fe562490d830ed450cab5dedb0be5078a0bd883576719546aa34017a13f1b873e94145efb4f8c07e752ed84d7093bb9ddc20a8d3e2a3e2fe5a07a67772a5c183fd20cf85e955dc0e45b380348b3bd63a19c3f0a7777243c105db110a99830de955a41b073e990cc28834abc3b10af9ab343964a14eeece7deb2e4604dbd982edfe613bd890973cda7f5ecab792b51fa95282a1153e192864eca89595534a0a89e799fe120a45da2ed11208c8a2db1bf396c1d8a04f8672a004199b50c67ced5c7a7e3842f7096ca759dce3b121189109037532a752a2410075328639403b0c48f627b2ac620eb417b57fd88ef663245ed37e727c566972f4000c140dd33bf3ea9dcc015c6a2fdebac13e512f84de131c6856e318e3ca11cdba87cae101aae3912100a8c064446db350bb03c9c1586450e36410768bc1f4910cea2319c32ff6dd1bfb06614f3e01a540a01a894110fe605072f6d0b7ec62ed1d0336ab35f2c352559ee05a037a83f0b6ddb447475ab09b4e7bf4db7c369f0fcb7546d2529d2992438f61d69248dd43327d6b6d27aa93937a45ad09b2039e4c9fe9eb4dc5912a39264f0e9e90e96b4e05e2864c5f85b4ca0078c0204be07132028d6e36d3cd1659910b919745aa7f2959b41d698f9e6a28fc594dbb0bfc5d7b890a7f29d9474aa5c2db4f7bf429bcf9b4c75dc19e64278fa914ae35d5a689a0cfe1e3e42b78cb754e88fd6acd7565ab89a03f39b9b4b020faed8aed46aae04895eda9126b2d768aa164ec2ef067b197e00f855d65b1a7f0e7996048c60e5a5d17f6eac4043bd9de0fe67c7d24838e8d409d47261082d567ddca5f36a3dd286616dd284cd9ccd756e4d2fdfa47feb2996f1392e94dee07fae89be4ecfd300cd347727c856f2c5e31824066eca00b85cc188e89990475d8b9a0ced259866510c3063dfbc04bf6d37fe4e4f8ee57e88989a08330fc9dfcc6955dbc5b4b9c5c0a99afc821ac7271983fccc54d0e6177344fefaec6e9a4231141233b829055f20ffb086733d8cd68b21c18ce68b21ced69c1922e9f6534201ac21ff6d169f76f341a559b66854e47a66c46aee847f80bdddad49a5a8359d03b178ba3053deb928019044158b6daa311b030a727ef6896eaf4b58a66a5ce22a9dd4e4f4ea10956b2a36377140ac51b314b71e3caa0db7be3caf6b57319e14f0a99b10f060911286bf793428aee8d2b63f803e11b5726e11e179ebdc27e72b9f6309cddefb3aafb61a99e1c30a727d397dcec921c75ba1f0cdcc91826c110ab31e10f95cdd012063dbebb5f8cdc61d86b0db6856ecc75477bb4da585c6b322076140285a415edd11ed73fed24ac1a7d668b55235c6b2ae8bd06fbd168941ddad1b399d1e9084bbbcd642ac25ff7d097005db6ace411077a6c66ee6e57bbd985250133867b5ca71d157d249e1b51d1f46ed8d951430e1e33333536b6c0f8419e667df18a5cd32c9aa35932d32067d0c9f41c803c5147a6a11a29ea84c8cae7f0210afd8b176126e64bbc1371268716f68b3333d1740abc0927daa31a8032e8b78d3be946713ac9eb4bf743bd44fa246131c71ce74525a190149868f412911425a1504908521db18674e78d897bd0782d5d8f55f6f8d0452f71370aeea46bf7c61459fb9689b22c9489a6c8a36bf7453ba9648912fc123a26e250217ce31add971899b3189965379986628c0a66117eb911ff9043580a2c471c69f244cd1b05843222fe64586408df903914ba289463de1bd12684fd46a409d104a43d5a059d2d32e5746a76801021c2f1703a9c902ae808c92ab365b6b8219c0e6724d39b6a4a3fd104a4590deda80694a35d3cae673704318372349f8b47eeb219d82a77a48edc9144a01c72fc6573f1b85ad715cdd27a341fed47e343b3ae9e1c0fc201e5807440429a75c121c78f686a4636a32a9a75c521c79b8840134f3601e966a81005232db9eacb898965f780d802650d52bef28d1725e8c9df143719e6daf9b69e8ccdccb020c7c40bc75bfa69efdaa90216391d633c86a70c4d44ee49166bd83179b250c3916ee7073e59ac8109d304a4f46322d2528215260fb9a29fdc0d0f7cea3579dce0e8ec282147094bf82164c8948fd704c444a4967e4e5aa52d764a474a3e261e52454a8065f2902a726a3e3ca8a1dbc43856e48a5ebed614b9a2cf746cad95d369d6756a044323f98467de10e18c6c3b5438821be249ab95e9ed9fb42ed575713a9c9066c12a14e18a4ccffd74395a25cbe186340b02a96227d316cd1fb7d39369cc29c215f2c7f9643a6f8ae085fc717c982d1f4724d35f35b67672729a356f9ad59f3f2616992a61b632cd7047459e3e09a9320f04a7001e425ad0c23214d2021f688107205786425a60a32304052de8c35603660821911999a110157021ca61836fd953ca2f6c10e51b622677844c5cf946fcc3dd6427a7b8c9d78e0a73ed64adcb3ea3cad15e9c540756621f7891c73e37d5cc32cb6b28f914a9221f41374ad0e3ec95ac3ef6933ef90b829b33550574a9b251cd4006719383a4daf1a9aa20ddfcc0621e23b8076fd1ac0fe6da897f8e3db112aa66f9088ba011cac0ae7ad53b61115996d7b03b318ebbe431a9123ae8f25ae842b9025df9ad7391205187469c767b6023bd8a98a7bd1c1b733c8947b3e4e3e709a04a103770151faf1d921539c6209a908350421050c8f19aac250eb68923e1ae39d83974c73c871cc44dc473269b82fd300fe6d9e05534cdd2543328e29a1182d5fea966b22a074b63d50c72fc462a71f27e97899317bbec6a6097f8bb76b27c77354e72e5fe611e244c72c541dc4019f199146c9c33b088fa58b9206e72fc76a388f1a2ce4535a3ca117f71217fa49b1cffdd78ed58173999742355a48f5c919a0055241e241e200b727c9c3370a600aaccfee60b62a95e58a66d5c179a1276208921942187e05af407391b5e3e52e5c218165b1e893e3e1d15e416f9c3e09ce97cf9401959d866c9d95182aa0cba491c6c38b2738fb1afe4b1fd288533d0ccb44837d829ea2b0a43e163afb37412520565515307a593d9ebbaaeeb92dd0318e89869d9a09db0c25aff068be9e44a03b3a8027e0a09ebaf0b1efbfc26bd60b1633fdaab30bb38e210ead063a6a5e6b0f359851d621c567fb04f11e1afd3fb02ef8671f4623fe4af4b65a4d821f6c6b9d8cd1aec87dde40a7f624ddc116d9af5c52aae1d4b0f233705bd7505f5f587e6aa5354176b73f8c026101b3bd4c5061b67a668af1ab126802a10e28045d05ca30a72fd14b0080c65835c230cbec803cb897282ba10a48a1a9c1c383fd624aa3a254b268a9e2a0996691bd78142563422954c242754494a6512bb134d0d9b0e3861381ad95844ca05ab522274eca1c31c4f80617d8ec7d67f308d8302fb0ae4c30eebca1198e4b294d82336a7849f189535dc35ad83438325d22c8963627691f01f2afec0a883a6a689808fd6be699a552fa5fc9a47e7d1ee3092631032cc420d72f2a6b28189a0c098b0edd57a483abc9c912aa3efc022a8a669218bc2a23d484d27d37cf61c3e505fc15b4af65f76136e9d4cc87cf6af75f24b86710b01d23ba69b7efa66823f7dad334f87d94d2e271c6df6d6c950b771da832fddce6922e06b8d25fd6b9ceddd1b878455a7c31692ffd94f97e45ab982a75298a012ce117dfc9041ad034919b6f4ce5e59d41b6c1a7a0c19667025672490845cc18f70dfc096acd4acafd4de8c38fa5d2357b069e48a06961ee6b6bd89b933fc98a04f3f038db450018db4d0c34b0af429be5c59cc04767916095bb49be5af753e9bbbcb611fdb8d7c78895d8dec9a86257679b15793f620ea6aa1ef3f10a992471ef2bc0ec4d2f6e329bcbc4dd31e6c9da6212277aac8137fcda39302e4930ad9a18010a39483d52e314869c8787bd4cbee7366b02fd997d2d6c618638cdd26a55471c289fcc1302067a0cb6fcddd40025ebb6da59452862ee5bb8360c61f0672bc0dc5289dc8da8d59ce6b503b066f0fecf17e31f2470f43e325fe7ab40291dc57ccb618a576787334f6c6acec18451d6bcc1ed8a126dbdb36aef376e163b768dd1269f4aa55f35ac3dbcb52c6c1f6310a32c2b6f9d8ae31d80ff234b16d28972a70969a95bdafc3fa8b08c77ddbbaaddb36796edbb42bfbec878a62ce3c9b35c560fb325da43a280e6c7f8350fb51eb29bdbed6c1d9361ab21e65be6f24496619e0f000879dcb01ced2254abf29e42d658a5fee5fb0200001f8c32e4a2f6aba4cf4a27dac568a5ffa34e697d1e4f92f9b2d333b926790223f04c83048112017f5b9b8be3468bccf9df2d022940815d29ea6a3d21eeab3d9c17eb487f6501fad666ad88d8c43f9a5e44781e11a3077af11334784e376aec00a704e88fd341aada60037bb6922e6e9cd5aedcdac4867a459759edba259427c9ef33161b487860030fe61990071c6b39684618510b75bed693418b5e1e214ab94a02f409ce21ab5baf875ecbb11ff70d1987d9a4531bd10b4470296f6d4a05bfc8af112c2ceccccd0b44c217e752e42e068b1bcd58dde1b300ea10cd3bb73317d6b0e7bbdf4c8a5a64bb11bd721944127dda23d18b7ce48d1f57a204eff7ff4a2d75581b8e81545adf52e5e8038965d60b903e214087ce3cadd5d602964ee700f0eeb11804623314b040a763383c01f86c20058ad3e006cf521f097922f2336bb813dd2acfac3f1a19b69d68ccf77399a1580cfcbb8475c6bc122aeeba274529cf66688142285421866ed87caa295959414cffb51286bbdc740a1ac05fdc3724aab4e3e51286b3514cada929f50a8f8aec2aeaef26bc77a584ffbdc88d31d336e00aecdba6e47d7e5686f7634530656e55bec8ee757caf7be38278400423286bfaecfb87b695bd115f7e9bd679197e5f76e5fddaf8db85fb754eed7561c7157b4167724cfa74a46f67e10d43eb1448aad0fe58340a09194fbc51c31ee17ad3012ba5fe7a8d7bddbfbb220e0d2c8f7058f471d263fa8af94e98e3d82fb301d192b41bee8fd66aed785a1991ae0b003412963f883c99d8b0170b4316d803b733ec06d20edc19432c93706c45cef47435ed765a22f15c3d0a8df4c36b0db26d2dd70d9b822560676c665e7223b97946f241012a89f0ec3ce384bb74eb34830cba4224429579dd6430e10d31ba7593b301a0e176c9df3a6189065e8e034ebd36866cc137f1efb816191957024bfc830881286e46dd6eb57c55f3d8dab5cd364b744fd009e6dd1ac01340b36abe23904fe621ee21fc442ae778146603770c63440ae44c80022d7935c4db976596bd15ceb272ce27ac5433c886f43dcee09e236cf16ec10439ca5e14ad34ed21e00eda59bb5b30ea50a895421c057ee75bb6322050922ae09e1dd745dd4547b880bf3002e0d2284b876cfb4fa7593107565c2df859528e01f964b1250d2f20f954bb29c6249a508f06f25ab541eebdf5587288b65131db99a5759f967f38911ff50f9e4edd3acd5278a887f36bba071d82a598f5ccdbb88f10f65f38b9e7f71d83fec7b07c0b11ee9ddbb02f087794f408ff716dc432355a211ef99c63b0b8d7704d0442bbc93bc07c07bc93b0b7ff74ea2b5a4f74df34e00fcade44f6b49959803aebc7b3f40cbbb015ade8f68e5f94c47aa7000663d52450170e5ddbb11f843795fc19ff5aea2e39d06ce7abc1391f548ef5ad683d22bef13aebc4fef31f087f20e037f367b17027b37e10fe5fdc29ff55e7110af3d5be71204c7411d5aca41547c696169674365a373ca3ba79c75d8d5609de3ba52a550853bfc8445980e8f71dac445385818440938790a49c169d6d7334f184409ad3caf5da16191270ff2d77cc061515c6d15ada5dde48993a736e2ae2dec287f33e32064dd2f66d689b81fcc2213b141d8b9683a72f8a858d36a9a8858063baf0969d6bcd6bac16eb01bec46aee65188384b739f453cd4bd885b80bb72ad5b22c683b8d62d01e329df348e75691c7635544e44ec6a10e042c4aec6ead761c038341d0a716f5c59886b9d4b7dd6b95c42e02fe66aba423cc69db172dfde54b91f0ccc22d338115fd55fdfb20e09025c88b394b888f04ee3c2f686f8e59d00f7c6952bfe84c003f865c47affb01b25520edb1b027f6d247bcfba1a29976200f8eb2db237a36a57b4376b1542880ae3a66d86e933be95742e3370b43595f2545723e529879d4b0a9e716736a994c81f0c97eb61fcc2da4d7b30aed6d25a02c01f8e2ce3a1ae7db01f58b0180e76d31e7705bb9ab71db7d3deacb37f707340ec6aab1d4af6fe4520cbf89cc8326ac4f8ead885f1d1d8aa096bad6bfab585ed4c31f027c4af0b71d3a56791303432f67a6168e4fa937720ee1733108f9d0dec4160afbdb9bab03def5bc98d884119f3f31c19ac874f07e29fa6b5a62d5d14eade429a05040c1200dcafadc03d79fedeaf81dce743c95ffb7cf2479e3fb99f1c92e74dee278fe479d5fde68e92fbcd23791e457fc2b03df84da32a9b4bed63c2e58ff6648b73b55ad7c41d6ed606a47526d73f6e9aa5e16838da6b76ddccb3655e21d3ad665d58751d4a2dcc63574bc3b9b41cada5a548158d0870358f843cef842c52664a8ed68232e6a7b5e4ccd53ef3aa2bb0dff314f1c4a022ca60d401459ec8c00532007972ac79e2091a6cb00b6d373e62924c0642a1788168847d0cc771b62ff70b702e91457219d8b62b7ae8c20b884417bd3b1791dc7028948138631be12fa633108df842b1143119f5592a1d6bd6c822415232fd44fac9844bb86ced459de4926e229de42fa3db9360d2a904c3702829121d762251e97e5c2eddde2f265b6ab15c2a9dc270f67ea6631f5d2962063d8adebd3b25e445ef4027390824127d261cd31946e6ee19e876e744f7054472d149f7747b47a5fbc5e4d24577647f3ae924f765842de826d0277a76936af417fbd24778c405abb2615f2ae111fe3c90bf781186e172177a0c49edbb404c8ebf372bd7e2438a98a5294799385dc001a397672bad75d64965a8c785735c5fc15bae89678cd876660ea1b55e9362776298d25f985e188546356c10a57e16666f0cab5a4631893129a56d15f0c418e32716e3c4a6ec5c6a4f6c9e6547013c497cf5b2fba6c44be34bc92b0dbdf86fe215895352a44a6ce9aff44c0f9640aba8b356da91075006fc4629ad357eb048869f59748c30a7d65a2d0065c0d7fa596b7d2c22c328efed189f29a5141600ca801f0084157f95d62a6bad95d65a6bada85ab18b524d08ada2226b5561873968b016faecf3d260d70a565ae6755d2a0cdb168a5d6543cb18be11ca17ee410fc5905372e702690c828d9f995415e755c5cce678ca3143e5389b0024cfc72618c933fb26b91ce71de518af0ac35ecad7bc5a8ef1629ff7aa5f4119f4d88dd1e5785d8a3d2883fec3be90e38541b8e09363b447bdf6529a087ad9024b8fe578cd8e328d3172bcaa267204d9a94286798b1d94012710368802835ce1060b19d6d33b514f716418c7e5aaa370823efb0360cb680b16b640232d19c661e5aa1d405fef047d55c55f5315b5d7899da8db6b05eab13b719dc3387c4427eab1631887ac424d1f9830d352372dbb4c0bbd18c6a13dc3aa88033bc5aa88550ea0cfeec4b31489039369d9ae4c0bcb76ee7242185a332d1fcc696267bb3525b776b54ba47b9a081444ea8c5c75abc1d27f7126d6f0d82fd6c41b345cd57cbc4cb63151909d5049d842310e95c448c42c2f7dd4c00b332d540b1e679869a12256a1d5a29200c52133d342b18f8963ab45a605bbc27e31f200ca684c46f605874d4a29a594524a29256661c9621c11aeebbaae5a69c5df5523adf18a914a1c019bb272040b6e9b03e6ecec400cb2075798c316934a2618c9b3093bf21442ca9d4d4aa89351ed41d911081606e9c28e39a9608525d8221b14d66ef0d2cb914e1478a5eccb788812bb27e6983146288c018592189cd3fae1a605578803ca2669dd3acb1ed9e5cd4610e12a667a237661b4e412b15882cec6ac107a17c6da435df157e732736357473238c18a2b40199f6ad8ba27971abbae0bbbe675d5d3eb9ab5ced74bcafa78ebe7a43a99fe6496ae5467529d39eb9c73ca867d551167192c6e29d8200a0682285ede2e370c97ac65c2679a8571d7381c2fd604fbadac4814f7c3be64a7f9833d9a0760a09802c74cb334dc5b9c26d2441d73c6199d9d45c60b6c97024f50e002db13cdba62469fe098509fd11bf20f7f9891e1257c2b447ed81815c080666d317f35cec0706fd15ebc9019cc4cd1ac0f1259f9c9f24774121790f7804a6c297da5aec61911cf9e4c500cb31daed108ec7abc7e57349ce16b25d6702bb0893fe28d9442e86fb1a1952b08797820cf0e4a2707622b2cdd706666a60a36fe896b3e4a29e585ebe5260a0525250315ac2042052b7af26792e19f3f140f88006428c4ea098dc91a692379c896bcc1c969b55aad56ab05458a8fd7b3b3b2023d59b3d2dfe24584a7c7e747ce489a56abd56ab55a50e460d6a2504f592162c3d3f259e9da3cbad53738393a3b36363636363636ad56abd56ab5a0f0813ed007fa409fe661c3d392b4c7e7a7679aa66bdac6c6c6c6c6c6c626f2b45aad56abd5eab169e1e4e8ec10893c36363636363636cd1379224fbcb1893c3fd88ca541d5dcc6e3016d6c6c6c6c6c6c7e6c527cbc9e431e1a49d33b3bbdd33bbdd33b30a72f1ab9ea63d6a250bfe7a5c8954c06f6c36872cb1c21f8b0554a2dfeb09e35f6c430574cce596b6d8852699c4bd820ca8c1335b114d0ed3298156c06187e0b77b7cb22b1fc0d20cb8f099bb19ba506f27cfc76c1089b95c9d0ce6565251e6b9a939202273645f6eb925726b1f7fb180e7c6c4426c419fd79e7757ae38f38a35f634f26349dd0c6264f9d78636383c54a840db2ecbb1044f922f7ebcb321b82383d3920fc45ad5342cb5dd6d53839067fd8348bfe09a902b7ebc6dfe4aad44725926f5b87b7abfb05baba5f2c12b475f79319f4a2ebea37d0b7ebc50f3a4b5faf2f1d7e8731febaabd7bbae6250c771dde34d9d56bc68a722d7ee8add411da769ef1ebb714ce7ed9f9c72cab96d31ca29a79c715362bbd6995854b7bdd340f8bbce3dfe09a9c2f2eb42d4bde2cf46f7faee953ba81e84a74dfd22d77535fe8ab9732652ec621739ae46f76b1dc7fd62ee2e62a8a87bb43a79dbae6ddbb60bd71f2f2ef793d0fbdabbb8f1a6e4982a853f5409ae274c624bf8b318ca1569d4755554b55710080412e197ee1b8809d1880b7f31f38b99b0d697ee1a4e3e96a3bd3b08043a082fb1d56b18abb673bfce2251286bebaf73dcbf98993d350a72fd8b381afe62e605aa4f4c1008744dae3e7bbc01752e59476bd775efba6fda513b30e26058ac17f6d520100804ba4caef77b7741f7abbf3699cc5d28f2a65dd8d671b1b379624e9e998b8a96d9e84915d88a5c59912b52827a3e41063fc891c21de4a43eb09b9492025265bb249237fc2855300c47b8ea7f28ab655886318410a24eb157fcd179d10c8394568ce5cb1c48fb52c136bf121cb69432de3ce10752ca191f383cc1c6a9329a69e9d14c6669c8e17c06b3d26a25ee8e2dd8e4f326f1b926a05c51bc853eb0c1b6526542ce09167e03b206363a21b614746beeeacee55ac9dce9b13b917d3b7655dcb7c316ecaa3829e513397ebb57bb4681fc25916156f2843cb9ceaba22a62db62a50a86b2f55863c73094ab5a52b54cd4cc427e8bdb5651786a44c946ba5bb6c8f19054f493bf512bf73f6fc443ae7a349331ac5ecd042ba1e4c855c7951cff8d78641eb941f7422fbebb40c0557ce87e442891eb5172a40a0a4f4eceb0b640ae9f06723d0a8f54e9e841283c283cb9b773975e0857ddd978d620d532149316d8451c0b44cb7ae920893c0fa90a7d462b3da4f8eb67d98535c358ad38c2ac48231b84570193a5bd29f1115b5f71d2c86da5bc87674a7bd785ad3c0655e825b621b9827880f33309b8829ff2856c9988d1608ad18678ce46c2a4b15bc6cc23ae9859e5cac56a2cff6171eb3adb603b07877d44ecdb4bbcf60d7b31c6ce46c433868cf7647cbebaeb7579961a335b8a99238e31e9c4595f2a683ae4ef9894c11521bcb218b35f7f1183c611289d5d59262fcc709665107226b3593307b27677f7ac73563a5b768e8dcb1f8413c219e9dce69c734e2c574a2badb5564aeb5569c56add64ec8e5cadb562734eda439f71f3c7c65f8f45d4ab5608218474e21a2b372bac150512c56ddd7175d6392b688a9b6b27061d3d818da775d6392ba8e340f3f6e74e2dcb024e08277dcc226601278493fb849737c2c2cf4748e7a473561426f3d65c9c47629ed65ae9a4909b7db0715e1cec2084f0b573818771ce49290a6c7c9d93ce492d767586c54de34ad093e1e73ca7c3c64f9869930f2985913f994e0aa9363f2d14b68dd6c086fadd0da14cc70883684bfd392f4a7bbf8d410e16720dce451f5cc36bfb10dbbea86e2c427849e7335cb2193e6209ef9d52a224ecd81e11f050463fbb1665d25ecf0b51249d556c7072b93f89d80a6c376cd07c23fe210fb1f0727fb02d011e1b6d3f42940f8899183128876e564986cd42e559f1d63c458c14692f0ec9b544249776e460391d4e47aeb22e58698d2024cf7cd303dd00ab60842bb2ca94262259c8dfc98f259cb4a4894756922af2259aec725d5e55cb9675c1dec00e3192a949a6a62ff0646a02320620b00b996621d3932c323d7142a63c4e909069b6376101aa986ae48a9ab6fc9980988a64fafbc02232edd925f14019343315698fe6f0918954b03d2ac2261e6c2292ed58530893f067512737ed793cf6307fec77d231b031f3dc986a322e58534da63f69c9935614b0bdcfa423d3f79067e912ed9586b3ad083f99e6efa4652ad2acc8d3accfda64ba23abc8132c4c46a21092e9737209a76443afb0a6ab40a6259ee42a906999d74e5a59158f32f1cc9feec4fce9f127ec288cc3740cab220e924fac8a8714077b76d2a2133bd1137a9293e9498bceeba4457293391d2d581e5907880f74e489f2c3f51c21f77b50a4d225fc30c26d91fb07c7c4db0f272f4723571bfc512bddc1e1d47335f6725870391c9066c10ca43d5a6fefc5e17037dc8fcbf1342b9e5a11a7c3e9c8155531f188d784f363bac1db0f12f1aaa9686f80f4e0e6aa110bd775c56ba7f4edbaa55f8ff73add614d375245e584fc94d824739265b7025e8f9f5cd15e4b086472c4273fdaa38722d047826cba31e1344b2bfd987864fa52a685fd389d9fbc9353d9c4c344e4a4058ba8a79f8948a6f0bb76ecb50fc6dec4a359a94c39235700c95c0fe7c3f1e194738515999e2322b3ab9eb49a7545b3e2156e9a05fa817382c5494eb3bad39fb048d28d228e6e14733392e92de87ed7c7d1648ab91a1aa902b168ee46aa602df4dbcfa62355600b904c399c0d7fdcccd6d3cadf6c5d379c8ead8145c4d36338b0f1dea7abe05a2da91d203c8694b6f031f1281d01e2039ddc2191ca375cb417a9e0841b2a38a1a6abcfa2603539d4c1461abb4137b21bf306b56fb6b219d8abd2fa6fb632b703d26ecc11733a50067d96058b713aa69af6683140f99a27532778c4164e54fd5fc42253d845ce0756757ae8322daa53288471f8481d07e9f493cbb4a4420f611c2e4e2718878fd3433f8d3e9a3779bceafd8d74655a5c34415f4397dacb15e5b1df238e5cd1371af04a7bf42934a460596ee740244320195e610e3b1c504f6269950aab1c100aa98ee3e421ec4408878b87b04c4bbcb5721571c496ab5edcd3e9be38fd8bad12d42390667d91c7a9a4e464337dd4c931679640a4087d34d22a32fec029419d2e03a2e0d35ee4610535b1252e2e84abd24f2e84abcde4c67cba30cfce86cda8eff4d2e7a964f2ee5c4c649744e72273eaa859ba163a4432d4220b46f2175ba86fb284239bfc4a3dc219a95f9372a594c9332ff52c2b79a9044219a9d7cec52447e82b784b08fb381d5a93c3d428883dbde4232dece9f374da2501f3e93975427d3b4913e41484324a1e4bee474b9053519c4cde708609ea742ab95fcd2647dd8f043975c20d3d13d4a9f492fb75367909df90f98423946172964efd5bc699987c6b13dc23d483e62d218cd91c3e5426b76996ea2c131c6754770a1f3ff9a602a4d71ed82fc2969851a7a7cde7d49d0bea5b343131790d984df0880bf62657a96e7252a564728ca1b904770ce28c13eaa6b447719af5a5b450db09d3688f5e02a3873e7ae8a4ab9200e9f5f5a44f215548f087615b098f6e1352c584ee88ae5c4510b6f58af8fa66fee04e8952ac00dca3564c693444a1918aee281333521a3688423935ec644f0d3a793ec6ca11793e0b1408e1504172fcf053e447febc3cbfd2ac20652892e7bd184798e439ff6051ff4420f3e9a57f52c84c493e4de73ebf75af251fbdded1bb7be3caa44358c48d10c864296ec43fe4ee7126d7679dcb8854723f29641ebde2afe4f4ef4637ae3cc25f779273370ad2633a1bf5a3a3346b84554a8cce9dc32fa48f708ccc5757e346fcc3758efbbeeba3d3d129f65e46a77f193d86a7c4a8bd79097c1e1317fe5e4a2e932926bdfe651423a55923fcd580b92bc11fc9643ac9270a4771e3ca27fcd5dfb8f2e825469aae143273979d8d7ad2519a45fac43d4c00bae8f3a52b8178115649003be8d841bf917dbbe84397b6c4ce013e48580a994718476c3101e8210af463f700d045e73a27ec4518476cb10fddd9d271a12b5b605701108618d3bebd9312476c89dfba1ea5593d4c0073a60cdd76b666c1981ae3e79c73c6d44ca5e43029d8cec5e7c37263b674dd24068af67a6ef38aa999de86c42ff4f22f528a0e7c32f3f213f7b0975845dff98b9962945ef5bc7744a691670c14933ce56adaaed63b57c551523abb612d25471e9d83e5e0b8b3033b37ad79cca37851c654296ae4017596850dd2b062e0c9426418440c3ff2168a5f7f4a096baeff626aa6ef178c75367a8949bb1a31f313b0588ea9b91f233312f2375e3ca6d2afdf32f2e03a8b710d328b33f8c418bbd750233bc32cce20878c82120c194ed48510c2d8402494504279655fbfaee6ecebbb4eafebd4cb178fdbd4d0cc5c17f5f21580fc72512fa5454259bd4f0f884c2fad709283c2b11f96676ec1bc8702044a7ea1d8435191d1226564d8553c5cd47f008105818541c250933f94098a13c12262ce9885190a8141ab5fb041948f46206c624b21283a3a389013003a379814c71936a037c3efa817774486dfff8c659a9661570d2eec050d302cf27717381187069976a26d434c7676b6196c9c8aabb15c07daa1f19218f97bc6b2dff3646041210e360b15030bdb0bd9130a0cac8501840416690864fb77c44723b7dcd95028edcfbc9a94949595ac43342a6222f2821149274609257fcf26b6847128d4ef025269086967a70516b6571a999a25cad0e368484e1c6c96cdf0f672c5020bdb3ba14ab899e1e53569afb715a04a521d548185eda5541c97e17398c8b89db8c8b614b87881c19e0d052f7e996c27f8f5c9dfb7998be5b13f580c00cec8ccb06b2694e1070bdb03004a736df23e1c0508eeda1e985cf1c14220b81cf8688242ed01c67bd5d7f97e1dc3b00bebe86832001c6c168c0cbfc108000c20500000035f187f01c3c5090c18304c60a860a44a5027125389040346c76d1a0c181976c180516170805219da404ca1b2d0485f228ea9793ea6becc47f9d829112fe540133b26e6239e9d93f310449102e46eac87dfdef789314c5e191f36de0f587b1bed98c58cc9ed867608656cf5c63c8432a88b2d5579ad3e3bfdf5f85a6b1679d428b26cd263795e7a38310c472b85943f98c24d864186d804c9b00a52309211606115a43024c320435a594e6aa7ec4d0aa82bc3f950c087921b255560cbf38792fb7466e50836898959382548958abd0b574cfb9c0ffb615262b8e3870da264124b5d142d3289c821bd13734a484e7dee88f8f6a9fbd4bfa993238ca752a98f5824ff4e2f39145205060602c35e01e0b4a15439b9aa572e1eea15f7cb64525fa0a450f087e5d401803fec059ef8b3159fe0949753f84b9dc39fc77271cee33014cd1d7f96bb0acb10e6b08b0ba1f7c73b0a624718262587ec512fb9a320f684f1ed55f13387f0cb85e35147dd386d684671f8e57ae8d692e00bbfc488c2a954f6d49559addc51a8185beac6542ac6185347a5708ca9fb81958cc22ff174835d0a7f3872eadc65912fb8a75229f9a9f37328140a8592252814eadc31873afe64f28fbaf1b30615238a45a26efcef8b7f322e9eba998bcbcf1d37982ede9d8b0b173529f96685ec45a3c792182364a956b8ab24c541716282438f16857a8ca9548c31868eba3031a786ea3d48ef96ed2c5dbaa6f64e77253746dae276bb05f6001d0aa9b282b103baa5fb36baa78b2e49e8964097f478314cbbe8daab695f912a977631b9d24e35d9b25dca16ed4e0c66a566de8087a833ccc4b33261d3a67365c67753da1d7dc0c49cdc13c748633cd239b96b0aa52879bed63a25c533fac8f126c790bddd36d3cd61c23e4a2917e6d08db974d14be9a477e9226cb5b0a5c3d26b9704cc25122e7df6c63cc210ca0861db5e7729aa207f1107a70e36bb13aeb6db667d3139f4f6b6431c39d4f9524556d0adefb45963cc1ebb1e15cb1f48c914bf4c8c61ae73a86899beaee042215088935845e55a9bc8dbac094d9da34016571b90129ad6d520cd1df1b366de40e75ce7529b902a50febaf2243704a58ab7816a7b1b067919f4d9b963d65c20aefbb6cd1a4e48be21f3cb657abdae75aea02640206c2af907930293627ab940a150e8734768c84be954e43a4120093a271fd31914da4a075d9280b47fdc33d065d5f0cbf512fe385c75b2acf893f5a5d2bb43a9620f21cb04aa0755acd21eba4ca950251008143af7b983d3097d532787405d0daef4ae6382cba07321fb99c225781444a27009c7a1be59dce10d77894449d14fdeaeebbaae4b2b495c3f779cee48f4be35ed5d9fa9939b728e40d7f077fcd5cd7498946a0abd56ed75de00c3ac45a1bcca811e02e12fa633d7714dccce923eb8d3e79608e17983380374ad82b04a8b2da9d2c4e7bcc106939243ff6052f2f675d94717eb6a84feb261fbab6382cba13701baf7a340f88349f1bad0bcc1ac09711ac7711ca7552965fd0da21171ea70b473d92e9341f7bb5f4aaea13be2829d1974aebb5e65f2766152b286e70d224827be4fa98832938a2803a22842d85e24f62285cc3d48701da6e03a0e9996eb9b0a3a0760fc61d104334ccc14c8cce4f0a8a1c9818213ccb4a840a605ca95bcc45ffc628e6f29444b3d19a59cb1e525ebe4a00eac7c9f461c6d4ade62b70098b9f6726027a5320e5bcbd8525629a594b14f2f3b17f9beae5ab75aa5ec4b76a5fdab4ad951deee4f8c6b0fd6eeae0d2568362bcea38109561e4623620ac61c4cc712e9928899cb81fd20cf1312c3ac95dbb11fb6b97336b607cda5cc34477a0573a6999bec5cfa94520e7800266235baa0fea29126ceb84ebbafbed7ebc55c10675cc7fe44b7845dffba7d451d39629159baafd9b95cf3baba4628415a7644d6b46b665875496c7e4a1484f6fa118d018142f0b439ec1c7af2e14dc69f97391cc839bb66d30266298f5985b4e91d31976ab23d2c59d2bfa803f4d247c225fc451dd99e929ce4dd4b0e5bc564baf6974a4a5e7a0a8f825812acd578197d6612fcb26192ee1f0c9749eff03769b626fc423ac941ef4e09125009fe6448f86534c2b8145d106794428f5ca9341afd035cb6f8a5f4ed366eb003e10f87bdc52c7274d0953764069d6ec961073a4bdb479a68c4e936ea387d24ba6874c25fcca28fb2089ff027934f175d2b12592bbafdec5c2c8b145dfbd3d5ac7d772e167443f8f4485352f2a8a359118b927b028126972d1e8d405bb638baa04b57f4adbb768b1cc9b5a7f78569c4054bba3dc94ba2d9839e744f72bbd3fba2f48dc2ae63695b637be92c6d4f2fdd787b630e9d1e5d108d80f9f42dea207977bf98dc9d4aec4bdf36d88d441d0344a2db8b4637915c76a26f2fb9b3bd2f8246078d46f88473c9925c7b61b84c7216d95d984d9144caab5a94f6e66934fac976d4767bc5ec352bf4b999a44aaeba0bd1472fd938dd826e4752bcc82190c9a097b08ae42fa4834e423ae824902d811e4725278d4abfec47b7ebbe984c7aec98b0584552bae8aa480eba8874c22a126cfacbe924379d4ef2537ba3833e3ae9a0fbc564d147a063a20eff3aec9828f908bf949c845f4e3e3a0c5782677b262f9d3cde45ed94901f9d76364eec55f8d33eb777b784ddbea1ee4745de4a25bb59d0b68d5eba456dd740db56b21f699b0d6d38742df41bbad7acd0b49fd7dbfe1d458a445fb055a8f4ac95b5498e324433120000001314000028140c8884629150302ad766290f14000e98ac50784c9a86498e440821440801001000000001001a04006e2194db9358fb9af3e6329a42e72a875ebd58afd2fcd4f98ec4b8aea9290fa8c8f096b9c77dc4368d00c0a65d763bba8893cb20613547b12209c47c83a3066bac712ba63966c3ac0184ab647b5ffc47c6df8dc33fb54689de1c626f4d30b57da2f9df669b0eed9d836acb18a839796afa417156ebb0ce938db75f9610b132d32d4aceb39ed9d807dbd0ec1daf12f02b61a43e6ed93dd8240ddd001f369a4a382797f56867e2d26d712228d8c437c87325f7f06587419556f3f52abc8f96222bf81fac43e41fb098964bddb00af8b8f0f7717d686df108182ee8a79e2c19824332583d1004cd31e04164390c0931c5b0eccc914dc4dc52538aca405e7eaf6fc63b62256d6f486166c7a7728a1f8c860d0a4f1937d9032ca27791c0b39eb086b19ed5eccd981690d5b8f5fea47adf5f25e412a29e6e89cf99388a2793996e005ba813a387e4348dd0cc96e7f4207a5bb648082d5e410bd4a815afbf88b3d198fbbc123e1e9cc66796bd2db3c4f68964d029b0f0a96d3b88dd0b41e9d947b6e88f50989546bccb0aee09a63f4c1404ba5314609c430a548fe512684e46396552efe808fe2972de1cf49bb3a8919f8752a586dea516445f3b27696eafc406a177430139a5a4a6cec348ce2cad5972233f57cd2b6dddfc611650df3515feede2674afb08a137c8bfb09047e8b4409e7c338f3b1b59ca551961377e5af622185790b83ef3b46d31e036874087e693e0efe8344a264ea50375c20f8528be84e920e1c0820474473675ac7ff292ded7365ecf4f0f90dff64c45690f07227f345ab1c1a54ee307bc2dfc8f304c1c35a43ad5258622d132c71bdf7ae01c127380358b3b97a66533919d38a40cf2be9ed19ae908d0da911d2bac7a8279ac206f37a17f164251d100ebec61590178b1490c95b93c8f33b74c0a4a25e5dd7ea9aacb70037726ffc45a5e3f86787f71d26ec598d53789a55f24fde9c20a61df6c48ffd8b17f0540503c8d235bba258737847b4313c26a9f661771056ffa46e54244ad2f346752e877a324dc99e2dff09fb6463241f60f54564a4145a805a3bd0c33fccf699f5452d0cccb21dbc5aff0adaab7dfaacecc2b3d2a67775108c9d397ca1836622ddc4a405cffd657b7225c8436bc579294c3a2e6e0ce8d87584e75985408b28fba93f12a793989038371e58ff1ee7befe187d56ac70b823fbca3f778ed229b15e484ee1d2441ed9877116679a85c051d429fafb4e3f7de69bba46db261bf9cbdddf4b4d421672dd71c0806c4a9835c1cff629d13621ff4474f6f8ef3eee85dc173a691ad513d9e325e52e8519b0ed85453c57fc90b0bb916c34c5bec2d4c298175aa9b7eff31ab9cf4a7c1f432400f7adad0d6a949a59deb5fcb6caa7ad742a303199236f483b797e021b10b433e71764ca0c5e37becc7ffa385cb86ec59fd9d452527b15aee3d681f968a62f042db4772f9aa1d7ca6d9ca0846e4465329310627da8892b71a9be9e17c53ca9b7a6e9f134d77bee57f1ad2484679108ba4f72ebbd5f71108f8e4b5c2942ed7df39e3fb6bea1fbab1aa48cdbe8ac126394558c6ed15f5fa260a042ca5e2bb5bcf3a503eeaff9f71155774c2e85ecaf12a65519ca9222beb2e2ee973aec42e7339965aa5eeabdf5f233e6021931aa0f2c31e04e9f17c2c2baa0cb99228467c8c052cd2458204a235a3c70c8d2821975a88f6365b29de914648623f24f5a29994a718e702339735c79197f489a0152e6c8b22e8af7698719ec219b870b4d7d72adee3158b57c4908476e702485f3665092c036cd319a99b2dd55e9f5a61ae58e2510b289bdaeda5b8035f136daac859a964c5225edd3c0b8c374543929f466e930f4c58d776c728db784367a3ad78cd799e0572065dc6a526be5771e961b9e4c0bed7c79f2e5928d01e7c89495385b370826e8395da4c7455014a77a02a2685ad417ba0199e064f7eb9d8039216737a544a4206cdfa6dd6c103f54052513f0fa6845c9b780fbe1607578642ed8cbdb04608062dcd99eb6c9156fffa3359bbe5231ba72c8f9d731a16ff18b1e031cbe472f2aab17b098eb4f85a4527fa4aedb8dc0e357d5747a18fdc0f5223909d85a229a79a8941f6304d42cb22fd4dc4944df4a8186ff14b5f070fce4abc35dd0adac68838f3322744b0cf17d314dfdd573587efe1452382fb80d4aac69291247c9b19ca6adfe2c572e0570e13d5792ff81ed290851cc02e002c748987a7d1bd79c40c2efd2b95b59498d7c27787f0ad885f8a66c1249c1c3b639a73628ba2ebabfe12c29418248028c939593fa3b7f8a2f1764fb2bd3c5a4c20d3eb7edb744e9726d0624b71085b642f202553a809d2085515339ebade9c313aee7a7ea6eb355e74bff389e83ab161938bd42d3783c542cdbcc616fa0917c50d63dac8842a5814b37e049f53932486d0865397c9a26453b2238e9492c09d28bb17a519af3b349b39666ec0a3e00d7811022b8a6bd8cc18448672a7daa846a0516c3c0d75e10c38dd17460f513e88acfa4da0af8ebab74c6d7917197e22c7c646356142e88a06c99c05462b4450163db2b240f6b7503d9d74034853923a4866d70450fa7c1535f4cdc6871d1ef69478ac3c6c894c667c88eb320b7bbbde27c0e2d751758803ec001a67254fe22756e47140d8bd9150553464f078ab7a027c650c900216db02e5e320c21033d5e326263d1a4fa9834a687a51921ccc503be1b557c5a3d97114721953241d4130b34e62609c5d631282b9769435ea3e26ba8c64483e752f8ed06c0b08bf93c76ffc18ff0050367e8a52ebf1e476002ef65ac53ae12bf2b753669067b658c89907982404cb56105dee7f9ba62cf830bc1cc92dea3d146915221db1e611e43109547d9dc2342cf13afe5d4662112a5cf332e64181d4fb1c4c596bc05fb622296dd3e8c89578b9b1dc1476f3af9d6c0c7c8cd38d1166193c4d1dd38954f9d3c9ae2f06793be5d9f762a6a117972fcca930c65ba54fa90810f95d5f0d69261bae36783a701532b57ff45ffa23689f2b6619434b35b17e16c3655ec7e5e60f029cece12a8a59f0959f785e422aa4a5d8fc64eab6d3a4ae1ff8e7858319a3311f2b6e45491e0cbe03d119421417da0d6bbd3e6cf65c304145d98ad1ab226ca3fca9ccfa946e20c47f59ee1aa87697b781a280fef60c31d53a4be2785770eb801f84414d3b39d5224eadabb41e96c4ac1bc1a3867f7350037d01c63c28ae238a474e1e9cd39d97b1ec33595c5730954fd5271c660f7f7d689bc75a6467e7b09aa6818cddd9d0a703f7155fa3128f3a3b6430ad23eda42243ca86ef477f2a2cd89d2046140f421dc0cd26bba33aac44975df6f69aae47dd9d4643aa527c4b0bd230cab05956637c533cebe7aa23f969b2f8d31f10b0bf82e8ea139516086bf78b67b547fe0f3d23945a85f5e73201f6ae6d1486b95ca9c3bba76e71bcb7fb3e34dd437d8848b2d996370eebfc78b9083bdc887f723b4c7f6fe8ddf232118a028218435480782b380523649f98f3f85981b9508cbaeeb5cae1e593d5b68b79006d946d7c4a223a6e2ba53cfb8d03df642a4d695eafa48e8356a79111f43210c6f9df847c5fc4b7a292f05c8491351263fdb96bebe29995f8ec10be776388e3dde35228535c02950c7b610b1fb85ba48f8489ad485374234988d08e0c3027382b95616f3ee85df4e5d706bfea4129444ab28e0944dcf7c273d79ade102f310be3d9c057933d16760a0de04410e981133ad83c2948df5690e9fdd5d8dc2f1eab74088bc44cbf121b3cf6efa3f82332ead43185b3d506e782f47b0c6ecd4358434c067122b5f06c1edc6ec1b0fbc43bdc7fc24705ff87c65c8d36f38aeec2602806fa9112336ac33ce7bde155be67c1e61e5aefd89fc8cc101a35f225e44dc0be1e845508fbfb92ba41697d1bb6f22214c2df788ac298ed2acef47904ea414d60988815f0eaa700396b86a7cc6b133ff4ce7e6fb62f01d0e0affb5b546e10025001d322c75ea0e6c93e576523956d296674b267243b28e81650f3dc041e8cd1df376027d80e03eef70c2ac13ffd1c9062e68e555456ccbafbbc5fc0b948072eabf12d31576d752e1197639eb5ccf3fc43569ce90ecee9f3c840a74b1e3f5f0c2d4be2d3fe9c92101da96571f00266fe2d480b39d923edb4572764d37886e9f18f24f09955ba1101dbef1a4f853e2c72642231d5e798773b92c9856943f653d3e6c645d9434db2760c6df299203f25385c735714d430fa5a6d2fb30370d1b45874be53144f040e6e03e9b52f8499bc7158d6328be642c064a4d74a2939a8eaa8b0780165638d1cf94030e87193b043f2533872d0f6fcb6aec0147235325792c353656d4370cbd1682287adc73af62c0687fb2b24ed55088b5aaef724692ed8828783a16f9648f91e70be7d4d080a29fac0c85516d0a7600b3a98e293d831a7f10f8df924ce1ae00b3fc60aed10715241e2a3e18d68e380b1bbfd5d70cc2623266c5408ba6692aacf55836ecf40535ee047ddc8c38c5600417e5abeb42df8e69b1b80fa1d71d42db8b2bc6ab6b82c59935425892859171f0c767215c7315b8bb27a73dd2615a2e4939added693f835fc56e1d4ee0471383c3689797acd378f14001d6bc82f50ec8655a102fce0455bc3af813f36c623029a6ca825f6c9efbbba1c1548d7cc6a5098bd4da924d75a2f8f3dc36bd0c3b0af0fe6efa72f2adc5382d22a364c37312e69e5ade212677824f0776c5b72c268a60a41d7119172c7edda4b6c152a3daf8e5b0b2328d1845eae0054e7f129026f04171b030889b93a8eeeab606063f91d6840173d04806871eaa43d547d5475d7f8f475c7636b30960ef7d60f850ab2305049b767b8203d7a69b8f704f3a12d710595954231ac4490551f63a8e848b02dbaaafd16905e437df4d5814872d9badf01ad18db74b66e608725cf8b3a2e545fc3b81fbc5d8e1d10424ed6357bcfbb4713a0238afdfb0313a75e39234e8c47899734d677afbabb90465fab3104416ae8cd67f268834bd008f03a8b91258a681f53537a34aa1142cf10a41bb25190431469630a90a82dd95526b694492cccf2900c126256a76bdcaee712ff79cb8b826c321b851dacbc4aa089bf56041b2eded775601657e5a31860edfb7551e95a6213a7c0d230f908d58dbca9efb8a31f641c0f080ecc7776100f4749b14fc4cad9274b16de9938e619e90e341185fc25e319e11dce931ee3d0c407723067391023aa4c66e4d6d5120a9604987fd94796f0eb1f3666295f279dd1a69b6b1f6f80dab30237326fb08722eacc22a51f31c6dc3ce07028455e55561ddfa9228766822b0f1ebb361b1085619e188f8131341d7703a63a1f48665e9509cfb049723efe837e307a8027baab66023125aa4998b98fb0ecfd6a49995ebccb6195598fe66f7ff3f1b5ac1e6de12c189f2a26a015d47878c5c620aeae152e6ce7c0e298644b6a5f26145122b51552de1148582b01f02938b91394f44bca2bbc8804cd412b9e634ecfd2449e77ddd08aa280f2a0ec6d28479e3aa435c2ac1113b0536931d5a87c5ff7da4044081d32cb6dbdbfd58a94ed9dece6d976afd84faa798ebc445ccf37ca8d73cb7e639c3d1d17e724619e19bba4c1e9c321e67e1dcd92472eba50d5c5d3b6e1d763818d6e98513de5fe0f240560cd998d26d85efce175e2b3e2b01f80b2b96d15d96970af08c4aeca9476263003d527ed05f5519b45ea4a28b186738ca308338f5b2888839249c00c97f41f53540e3111847c183e6e5e6d311cce32bfa4c325e325ac4d4d0249b7ee1350cf5abcde50e81ba41a51f97f5499eac7c411c991445898728130f9ec3af43619e45861c677ec6db2c6dbe83729f7556c13b9b37bb2bc0892ae1fc273cc647e1a2d647d805ab9d453b185cbfd5d256560ee82694f7a0fdfcf855a154f375fa5c9e349c24b3b2b82b2b2057c96ef9b3e338937cd067b97d930b82c6ca3a2c7ca1f31577b30a372835b0660a5a1ab0e4e9f687ac997764389529a33763c5b90817f9828c86096924f2f3884c3c0cfb49c0cf9a37e117f4080e2ebb684d650b18431a725f9ce32840df902da26361721a071da1ec83574938bb20663f905db4bc08f34ed3df0a970a26030449e206faec040acf4963f524b2487f360ff674b6f31200533c82e9c23f0059a8c7848d2c0903851a729c325cc36f448159a47928fd9d6299aabc4ee362cb04be742955bf70680847d8ad32413ae2ae74b4fb6e4d98573fcf7da6f8ec1b08add773c2c5fd0fc284bb384eac5b70b0433e31f8e1139afe4d5d9b9305159899d825246c724d84185653bc3ff9a145c4bc4d070a841e05272ed3913e2cbc906846fed581e97da173702f4c1e97c36f7a5a11b436215323c3a1d1e29e5a256fa0c54448b2a3a60aa436251a6c134242c9d72dff0704b397e92e301a4a35403004a0fc65a3295ca668835062113ffff96341cc78a9f161e0deaccf9293f5e19e34f2acbdf9812a2cf7c7478047ba9168949bef22bd1ab7b9792a59c57267d2c650f86f566dd2f2030891b0e599b2cd1fc8ed959345d1bac81c9c2cc00311622c4d30c2347f5a382cd25d830721c036e73d861d2f03fc2238a0166d18002f240015270b099ab807bc8c5df4525fbffde6a3c5da016a4ebdb8a180057fd95b28654e7f0fdb51273cfe22474ead8439c99d0e72e3416c2e360824a9c5fb272d63606b7d1c269584abf8f1543233cc5fc06c42c0a688e61faf19e768a48e11940b0728d205219110984e28fb7ab06e5e5b1a2cba9d1133f80ef5bf180cc80ef352901d7121115c3ba2f37d3d23e5bb704076501cce1468680e0034473ccf0c490a2d8c5e82af1aaad72c5a5ff4f7f504168023610a8e8385c3cbbc8d18918da38f2252e80b89db1eaedba30a76200bd5f840072c76b3f15b3472b46afc982463c964515b26f21cb5e193d05cdb17c6a5875c64ac8808fad276ec81172daa1983bd51eb9a60261e14290005130400c90d021b46d709a6278714b0c1d67502aed6e619fc592724eb8534d05725d8c4fefcb1056cf83b4b2fe6d7099ec116810d81ae9b8399acc006668c0defd8b93c16fbe9fa9a2ae7e4080fcd012e4c1916a80a9331624e2c7fb33203976bc01bbe0ded21075b4213592077fa568b245aae322d2a85b68b1e512947994c6fc9accb047f52e15db7963d92ea6ab0c4a88a66021e17d0e72de7532e20b1df9d70f672d4980656df8abd313a4e58ddd99b7a7c4f6fabc80806a449d9d65bc905fcc270d5fbe599fdb6a21942581fc6cdba644733b011fd1a85131e2f8653646b863d274581592cf60ae5287efe95365f3431ef06de86eadfc20df5088626b4af5236d7d52078d63812f8b46fd240c26f049e8f040c6e02b84f4f8e20f088f0762c758ea1b6fd030d3b81b85925861e042133de94dc25869f3195fe7203060fe0d00e718e9555434d80b502df1d0240e02752b8b755c443741c8ee3cea1f26c2b9f3fd7233b1f905162471e581ff58df6c606d79e21e0912efa1878e70157f4fd189906ff6ac2046be84030e7f32f80680484f8d60e1cbf0d2f73733e2c2c947d7d385a9dc6015c74aa3db42d7aed7907bfa2d2a1fa4d6349c1523e704b417ab12e5e0329f86fd8f6efa721ce521083e1f029a94d593569cbb018ebe7052b55fed60f9a7fe03b80ce33191c66f72578fe4f72ca8c1312ba5961ce4c0df9563b10bf61ae2655899132f0012e606acb3f70b959603b7b2caca0e9b74e4d119a48829b09d32eb98c6b6cc6e01d0598f0bb0582343ba607e600ab2f6a3c3a08904082ff2c48f75948fd077f7ef1b98b2f8ebbb349e85d98e60151fbfe903522396cabfe8450fa9c55627e0203725fdef7ad1b9a73cb234c96a8003aae2fb4f556cf64d2739247c8f6b98e8541139aaedbdf49446372c1558b70591a93a8702ffb731299b94eb55eec689fabe3179028ee83d281b804a08a4104d7518c878f11fa5a81547f203b404827111535bde090ea6bed4c731e3f1be12fcff660bb87404c7047e032614630e147df13fa81314af0f5c3419241d4de5298a9a656cebfe02391117ba0e03cd49af4a2e42e23c8ce7bd6f0dbf03a0f96bc1a88a145045f9409b3aa218c118b316d0364857f9d3dba1149180c9fd762e93b18a6c4c40e7463f6425226ddd8df62bab60fddbb30eccb5d41d1f63dba872d8d48fc6d1af59fdf6d2f2d81fec4c0b0b16f3ccfb29fd76dfdf9bf27ba27deae06eac138d16d83c3412620419fe1acddedd49ab5bb4d82a8d31f51fba56cb1306e50d195109f04da89682a0e9c2986471876d5ce9e2741031455a8562405179b30b345be2f54a47f23a3f832eb3009f966afb6c707cdfeb38c08ea2103032a5fe48e3e7e0781322911ed177388cd3e89ae632e6918ec54124950e87831e107b1eb50777c324b728ee75b66be3a046e6703b98e9ceec2e0335fec82fc7c22fe1426126ee2872da38cfb852a49893f1af5865e4f6e83b0a4e10800df654a5edb65d7d8d0009d8508315232fa637ac43e255c1229a84b8448512ef7c1c5ddf405e38bdeabd383cd64ea2570ce3e929ad6620da8782f60cee9bda9cf7006957751f035a108460232fa2b88b67a64b5e4491b6c09d9a80404c3d329694c1a8c8dbc5e4eda298a3ec41f2265f680556d07a046bfbae4b4979cef3991cce0ee7d79b860d988a8b7496d7b825b37fa3d05523c87863b8288c2228b430457e088eb05bc2c0bb4c723ab1c3f42ff36accc3d77e72fa4e77228b2dad2ad5d38a2e8393d9539a4b9f3157222b386b0d902a6a462085eab9096f89c7b8601911d7633f4d4208bc4444b7e82d49b0887e728c99530d012da3d4ac84f08bd74cf07b7ab472adaefb5ddd067bde86092b6151cdb4e734ad6ad41dda10fcbfac886307d89069a986411f92982af3717d106fe812f805924217d62c500f86247065f048e1e941a996f8e3ec90363aa45d5be74b42b4a89b19b53df2fb6da7368fe3e6ae5b258cfac63ad93d161f53cdb1d84858277713c1d1000701e611458239458951aab2463e056fac9aff0a7daa95482f2a7290e4e2bd20bcad91651578c000a73c8c9a9ee383476272e9caf3c92a3343ec07fa3a915f56dd1556b8e0ab35e79162985992468dfc9e303431db016e8a082f8eb5def3e271e48a306c409cd84515a94e83fee4b64a206c1a5da6ed6201448d25561f19397cb7e491da4d01533b16d127eeb4177408789aa4b11e7305f9d8ed1bd76f08034c7ece1ef58ad16db4522443202248f1f219aa600892083bb39ab1d3bd00b274c16ea2246ba295e974e0b6d551efa488d8cee5ad614d12bae49a234aba9ba0e7ff0c62f946f5799974bf2acdba5b28bfab176e9a432b95b35cf3b1eddca54165676c25e28445b6b942fccd5e66bb4ad33203fa491af871fc70e8cf94405ef5b233e32a03fc105fe0cf720d15643a6286c56d5495641c4f973c4985af195070c1002be1145b3f0ddf6f82ed615c5a1556a35deaa2dcd8d573d28b46b3441173ef43c0ef8d1fae37a7bf3ba54172509ff0c0f780dd4430dee422ad7e26084eed4f07b6e07c3dfb27ff2ec4f4721a7723957f2bdbe53c89cac198017ce5a3bd58b2ab3c16e8547c8b355a63de1ce76b1894021d7a170f1d506d401d941bf328ef882596e368b8ab0977d81c40b0e16a76dbdef380b6fea6e56b15a24605c12dc6732b390552c014a428459da753b7b04d03a2c1089d8bf0b4076fdc2a806c28523fc3ba1d04f94e7fc003b781b45c537a768aee4fd5381af8eb966241fd0bc5d446530f0b0a9244aa9327cc094f8ecab37d63bbed695b41177a4c57815f112391d1144097b69e5373946678896fcad58129bbf5b527d79272b808905e8e3006b0eb8e49bcaa1ac61d9b100210c8c61e178e1908ec624e866c8ff50888fda92a8d96d4ff855f4fa75cbee18f300d0c9556a48529ab2d9ea81e30d741dc0108c6cf57da152642b2cb154e910b6578f00801231823d15768366fa375aa924497b957e48ca94cdc1e47178dcdc28878ebf5b7cdb345065abee9a523238eab4d403a92f336d7287950955daafb0e4287d5efe3be43830b4b497d06724277cc571046cd575711a658ee5c4b7f6f43e34cf8b286e63a76c4292bb7e30592f06d745a3a7cab840b13a4df9cce74a49752cd54f931f22795db872df0eec3ca8ee8a3182658fd39585774459c7924827b206b10d5adc4decba3a580eb02fa9e5ed6cf4fab9980f5ee54dae8ada5fd5442909c2abdb6f16bfc92669a3ed43cc9eb67761133eb42bd4baaf3b1e3484a575c43a06725659cbfe23a2500e13756b0555e68224460573d5517b1253c230581ec35e7529d18c9c8c554b5da73cba8e22f25bc3c53ac52d2c244202853d8ccfb085c2ecc226a8f3966f1b01abaaa6befbf6b4b16158d7785e169d24ed25128eddc0e7e86f282d6cf15ba8e28b743b178f227b4d41c498b0a5e113f9c395bc69c2051bfa250ffe53fb8650934b6258d5b51ad0b211dea9432d166187cb04f0f3ce3fca63c07a19b94508334a30173999415260140e6e5837314b9e4f6a0afed7756171a84badc4a46d888a43c06e196e3d9806d3b00133a263eb337c80edffe32718483306899739f2570740954f53b9ec439db6cba285f7df3d615e06a9cac9e56de40a7cab1fe39f4c82ca90ae035bc399b3def47457d38b8f663d283c6e715eec17dd7e6795f5afd60c9bbb88e1e253c02f8d723da70e182e1e61604d109432e385bd46e4585ac7b87cf1f7b9de2a6cbe06ce2872431020da947f6c11b30d2906209e3fffd0f7064e98d4a7db73845f0f4bc8fb57698acc20844837b97165500580fd5c0111dba759483a2264770baf2161af227ba2590785701ccbec3e7618d7cf296fb548292ac6d917b8247e677cefedca9983d59ca19aa0df0801ddbc2d8f7296f1eb6ae6862c8f7a0db021675b7a444e3f8edb10d2bf0b7c6ab3c5f17adad6087d6046824ce41e1c14cc95ddce940b6d18d7a2d413c1fef1496d18285ce869432202c6851b3c063a4705339ab121f0910f22b600e883a158d25b70dbf3d161ab43bee1078c498957c33b0db5039fe9881a765a3a420d20346716af4c86384eaf5ef560f14db007e187de9f357066b2655cf0444a9bad7ae8ee98bb44a1298bcf8c24c7318466c29587188e32fbd8e81b24e1012b43b91d77b656e4a808f219c358d13cc5852818f3497750a4aadf40e960700b5df5d8c8e028c6ef62741873f109151bf57dad9eeec7adaca0dd76b6adedadb614699023ebf00922adb25703ad80c2724f586268453683b63519fef9f3fe286d68446b1baf6a9dbbaafe4944357bad99b6b32c214aa30725c4c2c092d4d2f5f87c0b71cd9895e6269c9ee650cd2489097d8a4b0f4538c4c6305ade4971819a4c40faf063b14a8768dfa48394e84cb2e3cabc8393149d8d49b75326c0d15a5d844371b1c2453b4145df619c4344ba0cf05f9d0e4edd2e5e61d9e51dd996c37874363070cf51cb05c8c6a26ec42b60c51d44c119f024c9b4fe209424c460188704aaa28b440b89e17ee7fde65170c81a5ef9165f3395e388bd676d975dc1fa610a4648bf5901238ffc48dd93eda6b48040665b3e59dd170cbb924540e8379bc7f2a10d0613adf8d9769007a9e87d36a66cb05d19f64ad0c1d9244b256b14a0587fc16c8708014c051704460bc5d0fa7bc82fae103f99842d0427a13a5c313092620f97a3178c33e277e2d10772513110840e861bc2d2e589b083c1f465f9a588c1aa1f6f2f0a7a679abd472236c3ef733ef41a2d65ecb2afcf2839e56236992a43d4cd88378c922a83c9ceb9a3ca2ec937a83207e24bda8ddf5399d64ec79b1f1dca93fcff4f65beb01bdb206abfd0946b8275fd7b47235ccbd44402791c276c8a3fa10ac54303c2dc8769d0ab758c19e13129e66d31d53326c50918d44c9e050cfb2f6d229cd0f88121864b94932d515c65526c3bd257aa186ad80275de82e03f75f3fea4881bbfd929afcc4a72f2cd2ed729a54e40a583b47bba6d199c8f40cd8cc6796d4194d292db6d293e5e5263b655feb159ad4e1973e0ea2e56974bfb6e453eaf852d64dd94ea6a58d6cbff972dd9fc95452d0f2165a027d8fedb1b6c093d3bbaef35cc287cafc8adaa443033e47949c1253df1acb997227cabaa65524b8e41c0539b3144b0d51527dae10af9c38b52ad72af95432a494296edc00b76306c369bee7964b2047670aed134bde08d44e8e6d1053c50f344304b20a01143d8e8f889e88388082ebe822aa83a7abd1031c269c971219298e4777c10f57808b8383c42550784dd8aa9db0f90350f54eae933fd8673e85e21c90ece762a0fc04d1915174c8e000a41ed84ff7e86853cdd2c0874e2953c0695878db6a75a843f4424fed4387dc8421f85058b1d9be3c6cb5fc691faacb9416be10f1a464c00eaa484ded940adbdaad5a22a403df7c17478063316842a099bb10a05f738158a4eea3f057083534605b98fab80aeba728b23602a9123fd555df3522b6a24516b5228299bd0133a493b01639f5dd279e2d4790a0cb83eddc4b0e9284fa26621fe376cf79901805d3c0ee7348d92f68b502c69a9886a120e9b14787d6e11d120ab73842c585ac3acf131feac0cec992de06eb78f3b4dc820f5f9c0249ade589d33b6fd0845439fa51179a2a31447987d9067b43632aa8359de158fced4cff56b07b022a63a78706b0fcacd0c3a910c68103d3272ea5e7087f0b77c44df59d8d3b96ef20c00f22562edcf0a01cb6b5f7f5d029b221019ee525447a2270b9b189b60633752ef8e62ac34392e353ec882d85c05fdc7cfa7d02fb7272ee6049bc8ccc506f4b914529caf0b532c4903efa3e01b2ce3a68e048eec2aed41b69a34847c40d479183501f1dfcc82fac9445d84f3a14279b7f862fde6d970441eaf1f2139c1301c885efe5cefb6ab0f0cff547abf6b2bff3e1e7f445d8ba5fcbc8c768b4e80fe8e14924008778382f731313129b393aa738498f4374e1e56b78abbad2d14250369c77a907dac890f88f6abda7db87ee0fb84521e4121edeb8f852d39be1142326e007d21f5f3ac1ae17e242bc201afcf7e578549d420ef414bfbc884cee9142e651be580880e25f27da0f9af964a3e616272df95686a72129e0116dc82a5dbda6ae04c960e84a9a5b3470d933e46492f8df90139ffd9199020e076127a6ac9e287c38406d445203c8ef978b19494e3ede8316fc5f409614288793ac52bccbed16f5d13b391ca8970b9f5ae3981c37f80757015297cf8d96e32ca45231740fc0d0b60173f404969f4e8ccedf8c0f2f8f9b560c05fcfe2c750e0c45b3b256c0cbfd2b61f0c2e5fd2dfa66bb585c0d486ccc0131d57a745242efeba8f0755ccf94de14077e905f771505130efc03ef03cee8f195bc492e600fd22991bf74751134c3b7c70d2a2b41a68018d20a6cb6a434cdaba3699f8dca2d1de1b6e4460b1ffc2e7fc475fd2fdb8435abdb57f6e0de37a08cf62179051264ce1e34e8ed10a161b6ec1f5c1d7e9bf754e091c60de0e955b953aa6b3c5efc75dfe5bfb13d66b68369087f13ba5aa46b08dd8625f1544705323ebe30e9c394696c5052d5315c031cc95d40cc49eef1c8de1b477502f18a7c7c740fbfea8f30290395206f0f8104b4ba76b2b6df131513ec3ac9d498ff88d3d55e8fa6adf51be3428b2463ae7d05d68da362bf731cdfbbfffcdcceae414a27f4111a11bc89a1fc0d17cbc400cc1a14e7a12450ddab4202ec76183ad1740a809769a4a3df34659649c07151259bce8be458dab550384cbf03722025d056764fc24f772d7bc2a692dc4d465e04f2e54631b515d3e5d82c78987c32f560dbd49c1f0bbf8043bb49b2383bbce85d1e81df20171787a26cd83bc6a746fc7200b02ddd682c92993e976f5fbc7c6e02cb4f48749ed18db9d2aa5f12c483f5b7fae896c2b529160b18e3d5baedc8535fea043696d28500742e27c66685340a7f666729002a2da75a29104e0a69fdf7bc1aafca8798577d0ee85b22e06cac29d8a17da10e690a04887a18c49a2560e3c316f6e00ec7ce0b7094778b42f3403313d6fab78d7d0171853cbcda0c9e10ac8f4b14bd4230e0fcd34426c8210077a138b6b69c734745edda13dc78110576af7be2c130b2933468d7597f7e062e48b9d79712b52d29d7d6d06dd577c33a7a0491c82ce1e419d76cf9b57efe71f7f88c026f3af6f8c5fcd6482eb1c63d49e80532ae6f2420fb4c9b7347078b35262c998f98cd69dbaa37840f9755d54e90d4f4584972bc3940dd21e5ea9bbf438aa43321986050a16bea4135de1139342609dadcc6bf04db98f1c308db60ae5d8ba0b2c67aaada5f12e6f4d36cb9f3f247a61ff72642f44be413babd829483f26a3d1077166bfbfa622c1e838c6dc0496e7cc2076457166da556ac09ddb765e11d110452f711a0ca60a83d25a1085d70cda536eed04692d1ecbab3652c28a5902fc0cbbe1ed21c89f83a473bd1821c764efd834ab5ca5e44ebddce1369bf229e8017b209ad7f9ed264accf375209c7ecc0d46477de8fe92929cad004a3ee72944541750fd51e34dfe0eea86b46046bded9ceb6b342c349fc599d3fa4e48eb722b54ca250ab570972b259ce34a11d44e480a95f08e2b5db8eb8a12559cc80a74618eeb5ab843ae78d97c112ea9183ec2bd98fdbd809ae061a1e1011be6ae1308e0df308b578417184a854c185f75be46ce0cce93b3b7d934041850b4a6f589c929795bb16003d190c3f1c543ec1fb60a1d9ee62a678222f479c6926d155822f9241112de208710a00e538c8eea67b92bc68f3921dddea216c671ad0b775cd1c21db7e0416cdcea61f834f4983e6c4da4b8eb5a11e6baa2843b72bd874d17e152c5e4135c8bd5d2b40aabaf0459072e0b47d63024077b003396bda726ecd118e25b68065856f56640859359613324b72906549b419018e59d31306f57ac82551642e2293c79bb8d885a0a37dfe640eb3ab11f72518cc7136df868f51a7d5abd4df9484d8d7c5002b1f9802b6258e627c0a576fb828215af1d233865652be3d6636a3297c5f8092ec4fedb851c6532c7834bda9c0a1771377068d5f8a020990c1dd53157361c610f5690ba82ed670fa2f2696ecbb4ac62c2713a8518388315069e658530b843c70be4528ae523dc8bd9d2d4d745d75491835be9fcb5404461d91cb40416da6c6199c0b06622ac98184b18cb3a9045fba28080444ea67601c1fae8fc3a5342762e17c5f201ee27b22681487823469f9c838d339e64feb67a426209c7fa3f7823ac407cc00db17c8083000942ffed21cec7b270c554025b0a7c1ce95d8ec8913ddd06f4e527938bd6abb5143ddc5268a504a7654032b3011d2d86e0b05863eda6f4a92fa2500707c6adcca30b536efe55a876fee3694729d7730307889e396b4d8c1513389308422121b20e4a8aa0ce77a026eb2e47931093a1c60963b126126dff63527c5a102f5d4b81c44d0e129d83e02dd8c3f5d21df486807e1a01d064bf564bd6b43d1911ea319b404b7c896323b890fda570a0cdefce1e120280e2378e76a228c7a1770900e4323219b2268bab80937aed68a6c7ac350cac593b2ac1b129249c53705c101e551e6502108dcd17fc7135fba1dbfeadf8da1d874882c9f87455fe153d060a2664a3405955eb9c1ea1dca52ca5a53e210931ea6124018a28bf2a56a102e19dd4be7846d295073ac4c095618ac24d2189e1b861fedc736a0d12b3770f0443bd3a3135a50cfeff7e350c888b3517c64e81f7bf62feebc07e9f7d21565fb9dd7591721094e52a43e3241eeb139649606a6be1b46b8d9034085c9dd9351f6b1f9e3b800b8f01b3aadb3da92ac549f00d3cb7fee9edccdfe4fa9d1ba1cda3d413630284db07521c346b7f8dae24baf496999084a588dcc121f18716fd48003667a0fe0ad886a1dfe6f971ec3fb7940f9a5557d7915375709ac9c6693e452a26f38e8057dda30ccbada1bda2884bedf891bc5024cbad012620adbdce1d2a50655ffb06d412a18d02fac9bd612845af7dd1963effc9757a0f3a3e4d838b2fd1cfe1f8f1cae667256c9f41861084ebbd69ee028a82bd51c2cfd67fa8267af29a7115c45707bf07e89996361d0dec0aed20095d34c2be004404e0b532b151b36e3626c6bd6ed2a8bd4a7ab37cae0b5882f45d05cd74cc23bf7bd4da1b789d96984e55ccc6efba83b5ff2e9a66fa6d7a12a1131158f1f1e0521433afe88ffa721ab36fefe510e0afa6e491556fc5635b63b7bdf53c2de119d09d2d10cbd510446a8977e55d6bd0adbff9b7cb42d22ff9fffd7aece1b7dbf15d04a2a4c042f4395a834a6158c3aec4fedf3cae49f45a0d85a7893038dc9b8b814638bd837e2a9d50863fc198306e87199561f7276defdb8132fa3531c35b6f9d389b0ce13d82e14903f0b1f894bb56087144e6b6e9a739c1556acce67c3f76dfbb9aab3a8d459b43675f2ba1c3a1abe6519042f361daae30b78c038f57c732d1e23f97088eac18e972390c19c98cd12f99f9ab60578f4a4a5fd4541b6c3e98aa55a217d194cf00f0c6608ed34391157b5d3858fb95fd08da595acad4fd5c6303c7ad0947f91731a810e4e4591c71e1fa79d400a3d23aafd8655165ae4db4dfd9ec4fd0b2f5a2cca56028a1cbee5c9677fe6e6c3a566773b130f8059fe489098636a71ba49e41b8d6f4e1300d71495c0e58666e145ec14803fc57844111859d9c2127ee5704ae6817f10150c653ce36c1d2db665db3d847e513f913821e951b65f3c1a4fd2e58beea2c6713f4a804f87cc03522d8c24001e49c30355c4cae05c247efcc20a2b0c837f47fa2cc9b5bcf580bb6763d36d2c651e020e824ce9516a7d23ad8536d47018c0b88fd117776f6df5d269db3bb13538aa42ddf7da55e23d4d9bb7393cd219ebb17151002883bd2d213683b7a6e4a0d795256c3460c07557630e72f959e9d864fc315b4feb1cc7ac6607266994dac8bd2027111b40d10dfed1baa22ea93e48bdfaa7662a0ffa5c66e6f7f9563e171ef61dcc1f3cc787b9547323986d863e7cd1419405404b129504204861b61139e2ee1491e2624532c987919fcee85287e4c4801a4843727c424fb6701c37ee9a650360db56458ae93cae191be49b1536b28281562b1d06f57aa9b36b0083fcd57e08100aa0173bfacb22d8e1d406d73bb3a88ee6f1b3e2e1532e483f36e6508da43da0b961529bb5568bb5228c948e4f51b7bb5581c8c1b63e8025b48edaf1348eb45924416b8b36e5a2e7ac626ecb62b55dc9ca31260f7299ebde66ce559c673cd21b2b0d2ab8a06ecd33937b1fb83ccddf2dca19a716a677c42d9ed10f901e8dc9786a7198e1265629d9cb3e05c39a6688e3a22e637c388225c0df376da3b8ac2579f8ac6a3918efe28f6f17429cfa302cd0a6dfafbdee80ea0173d60e9c631599f7b4231710c09ca0cbc21151b05d73ade888602f761806f1cc89eb319368519c226d2a66cb815858636657366fbaedb2dc1ae0a2df99630e1dedf2c410a52c0aa649c9b2fce92140f6cb8abce4c3e5ca451404abb1ed8bd7a52cdf046390cd2a82cbb551df2b89eb6357cdba3b8496430019135c53542ec0234b02911c29330b98d09d08d9c5f64b82825f3af9338a5662f012f0f3109f60d60ad5f03717f583548b45d815d801cc5cab08ab254108f03760e8accb714f77ef1f9a5d17bb45c5f0620150c6a7de779ae636e751ba568ad1c256308d260f75befe9895f9022d55e3b6ae4def0a1a43c3031627887dc11efcac4052dbe56166bd5a4ba8c5e70fc6e56869baa2cff67a963916d7c208274e94e8557bf265f3fe8ed9fe05b520aac53265962fa33e9436137132c7a5c1bf7f612f455a7c307c50b66dae1b26315b71719f5c9c2eb99d7d34bd39447365a50f691109aed0842c7cacf590ec660050216f44244393160f0877c8dd290b45da19456b5afb37c49773c8cc2fe71d18c21d9d7ebcf91c68deeba8ccdf0bd4f41dba37bfc6ba28810c8d8a6ff0a8edf9c354625f4b47123a2a15f183b7c8b24a6336a388835ecf95884cc5d9daba709ff9106d28bd989c0dccbf71e6bd889c078fb71f4fb7d5cc7a58356df406550bd2990e7cae9593a33d703ae89629311faf9e33b4bbdba32d3927bc5184313dc31cb14b05843bb3f2615058c500cf76bb44deea29c4fa160a115269f4b41cdedf02916a66ddb831d956d697cdc546082d8a310a2e58f9b1af296c4ddb89807b606ad6b0954d55dcf35eaa0c91e4291564ede9fa9c776cf523a6f8c415c2db956ecd516aaa6c098f1f9ffcd01db9e5a9718d17346136abc5b423a082085e46817538ad52a5f2db0ee889735d7460724335d490effd8bc93521d6f6df4029b5c1da09aac1470b82b2e5c6b4da4a97ff7656e7c1ada6312c30285d3a8de702fda875e4b3c9669904768d3afbca8c1edd55da498cbaa018863e82f11eb320886144a5a890455e8b6a676ebc88feaaa6dec57dd8ba946c96677b410a8d208475e83e80b355ca1196bcf3746511a7c946785828ee63422ad5fb60bdd548cadc72642018113fb61c8dd5e82bd5cd64f42b3cd82c27b050de1bbde54ed3e5469a5e01e2bdc5c386858f20007cb8c4db759e855d0a1244a2e5713fcdee740a1016588ab7ccf8e702033d9d85c14ad2139059f797682d12804a2db1aa109e8c57df7c9cc042092726f8291bf14e726f8d615fb4db8a2a5cea649323ca441e5e4cdbf9c24d20662c246b88ab55d8c115fa38c2dc45324dc1311d0d0306fdccf385d3496eba23dd57d72cb920c9801aa9b1383dfda5f06de7562b3d692ef56c94c9bdae05887986e201b4d425988815ad78d1a195a882f1729d09f18eb1b075d8fdd67a81358ad342bce40f5ea52377eb2677f47f96b20aba2352f3663b0490851fe147e84563899ebf5665dff269524683c2d0a8b2eeb20a668d761c653f14845904241ed556acf6bba6087327c041110cd2a73b628bb50c10536d2c5f12a8cdc97eee0904adc4a66761415788b958de7622f8947d48da65436d7803032c7e6cde751273ae7704030962b0a3b018d294b043792dddf3da4810030077ea6b6ecd1aab75429f8704f6abc96bfafa7cc8a918b838e96c869b2702268caa6a124101551d9e7f9d68ede38d88dd94d9a6da6371015bd939cbc30b474df8126107d9fb4329f6663d0e7375743755f5632c5d870dadc2767358ed26571a76f71df0eba9cd36506bf026a33a0ffc0e48cd384b93c8a5c463ea6f1e3b748cc79995d99058df50820bf1f1e3b326c0159608e5f669cd8f79be09e6709ccf6e72bad53f8f8d185489297715bebec30de8a421d09c2080d32e994f811046c78fc4568e04b09b61251820e64140ca6886d23e773a6414569a316dbd3929c4dfa4fed04e8aa047bb5e37cae9824b387c5d9a742e7b7a26ab381bba9f4ee22f4d9070711fa0a73a4dd06964bc3b92f7a20869d5296b3c1fab0699ed128fd8756f2e2d12a1ee0b8739454dd6abaf7c0d3e9b77cf048a5e02173f919f375485ea22c71d7bef6ff105045b59e931f5a38bff6b6c3e7874f371e77380411b9d4c5ed6031c00f02b8f49df041404049479b282c4b0e2e56929aa64200b4fb0da68e023848bd7c32f8605be3f25fdfb7430d737f1bad95652b1f8bdc4e7504fe8cce84e4a458a366be1755eb29958ebf175cd99a937c74c23af2c0a56bda3b7b5896cd64f41d4962d7bb6e14e3ad0d0edeaa31c354fedd4363005062bc15a9bbc40b6ab8f58001ffde0a8cf9fee58a30cad24520d9347de243a16f6ee43955b10b90f331337f330654450ff520c2b709885b0bdb0af0794f4e9992619e7c166e286bad53fb69f26b9fe36bd3a546d3da07c419fe6f980ac688e635948c3f1e88ab7618e5b6f2405329e95c9e858fcda59882a8fe6b641a472ea603a4227344a0d682a0c199b606cfc7c2c5ce7294efc09722d316eeb6c60df68b4c23ad4f5eab16cfb96d088d32376aa6776326609c8bf2e33fafd491afefa6aa6ad4a789cf08245ddeaacea5d3f5376d7895a8f293554ad6a3b81f33dece26fc5349c17838206fb9b1b75b1d83566641a6df3d255d86eab8bc4a468d923a061be2f5fbe1d148d8b665933cec81515e7ce16cb0c132ad2621525fcb8f3e1e9621f8ba659155700d4655037112018172080a675b05a72737a54353aafea2e474a34a9133308f337db6794dc8b1956aab0a3865acd42724bda5488dd1cb1416cb86660c2c38c1c68968f29e5977c848dd55a47b475f6c24b2878cbbe7316ad55070816067f3a05ed321994659f90b95f65a443f7e9782703a3383831081cdbf50c40408032074978aeeb81c9d99c2440d7128d673b7b52020190ea55fc3a7b550c53c4890163b1c0b8fb1ed139a565fb80ca4352519f20350b7185c6fa101c277d225d2affbe35c454802650299b359a641642d4420096410b0cb3ddd437eaa674af3e27a12246eb4351e339c461e41bbf130fa39200fab18ea7ee4faf5a7164a9b0e69f6c41efb34b7ee1b50036b795aad1a0cb09e156e595acb8bfd5e9adac718270848a2c907cf102d12de7daa4676e0176d21c7c7920877a644383ecef4be3c9c38a596172cf8cae3f914c1aac51e0f93a39eda9020edd69250a011c6ccb4115f36f417c636836c85ab379603f689ddf582e29f63bf63c15b27d855b1da0a500f839c68e2a43d6394075b8e8157c3cf9f8672b0ef255f0ee5787a42e5e28706c32fad1162a73f0a1408dc72383dcbf030788a5889cd3d71d177dfe9c691fe7dc023b795fd13bcd8a396a2a658a0264d3590faf64c5db993c003e2917979b406ac8e06a51bb73b8298ffc82717ad91f53551c2cf3a60b1d431dbfc16d1d3d9c6f198ad20972970324007ee68d6a7ead4181fb6f3cbb79f354a9211e60a2d1d95ffdc95f9f5f9eb1475e34d3340698ecad62a5edbd6a59523dd79792d4314f66b88aaa6b6c3b16f7f8a8663ebd09314eb8b015cf1de04ab984074e8c7d8860027a85fde8109281f24605b220ee300e9c9cd796e5262123b764872585a7e3ba29d425b1cc38aaa836bb468e2b55d2b45ca6c834a53b4f1805bae36e1282037d2abcbd19194945c9d50741f8bd78bce4e93c2ed35a19be7d263a77917f49ed8357e17d8da7551a23ac8a621dc27e1bfa2c762906ca6f331f0871444539b624b3a4c43447c4b2e42b1de690a22d2aed159a37e75d6ddc79c62660cef8e2ee265526c7371944bee57da2963b78a86124ef60e9ce364e595556c5082540612a509357b56a13e47ea3127eba8c0aeee8af000d5c0205703881065756c1860cbaa148ae8911abe917e73135dec60eb80540c7416fb0641722170b6d68c150fe7b294b635872a2b62c0b287975dfd82ac141dbc8237d837a8742d0bbf2249d5e1044e04bf90ceadca7ca9c1c6f434b8d34902b126ade5fb47b0782eb461ad8ee6d5444a19ebc109f2df266e586f39799dfccaa3273e955b42c705948548fc7f775c530b679865a11bff72105884c4ba318f4fc8059fca8c292bddf1cbcacf746f88f894484c40b1aad8bbdb83fa84dad5b56c89ade85c2a0d4b35952a6ec1a874452ac248e46e51f0aa05db354780072f4ffa1de0f641490b757306e28fcd6f612511585d555f4c9df142857be756959ada7e4528f36df26c0e3aab6c5a622da07181ed7651f44d7c193ef38cef4c7164f1ab3fd0441a479007f42e6dcf6f90a5afae47a6e0ae365619305a69512f5b950f09087ad24efd4c8df50242e1616722e2ecdff52a46c308bba6f5fbe7f520b98d01e098bb4a1a6df27fc285f1a20532e543adba856f957943409c49e521bea289717fe402602e372537e154cb790d8ebde3651260952f147fa8286ae9673cf4096507e1222ccc493f2cf371734e38c30d13b959f02c82496a1144b4cba613a65e69f1b373b2e55127235d9e4232564518eb42a7883943be85edbf75d85b824b429f34b6ba870a36a8287c0aa98376012010c59655a1e31564b8c6e50143a4d6bbf34900f76e9d005d0e321fd80fbc8f095e8beba545bb2fb31ea2c6b3a5e0fa6f8de73304c6a7ed16a65a7ca17cd65e878f82431a7f10190cff31cc11f91d9299480ccae46744c0cff36050ed448849f0da8e9cb7878c054b132e3fcfa507557e95a13bca80340968c3c8f6eed725c78365510a28272b1780951646685ff8a63a16ae70aed4504600cfd1526b1bfbf0af9ec08403b80cef3be92bf4783bcbdf050d15adeaec556912cacc4f4a1e5ed29684f0b6e449343f7ec2292189a07be234abd1c68373534a901a3b50e91ca591ad2e23ead3c30a9ff25e548a22b056ed1c93e9edeaefea935a7855987f233ffd6d14491e7fff21fdd2b20efb9209a8557d484af2e43de1b6c4ae176957fb5065cbfb2a9a13fd91a3d79bba4284ce397d80fedc61f6762384f11de5e0379b53bcf075142574ffa345a57e43190190a772f6a79c50bd85972c1d30c2014d5f04691d5cd0473e78adba366ecb231649ef53057c027da2ee6a7081cdcd76b3f05962b6118f7f8800a400b469da1c1061f28080f028759b0831f1e54b4401afaf9e5113d0e1fc7e7fed07670c8734c97ba088702a09e87b5fe8d254c915eb7a025b8ef32a8215176cdb7c366d97fdd5b5ea5ffddaaca11e92dcb5d548529305706cfa06a083c3225ff878e0c15119207b2c0acae416decc26afcadf85a9c8b91a8137942cc5a834edb6dc746f2846f5bd6cf3961ed49cee412ea3c649d6987aedba44dfd09c5296b487bc963278b0205f495f2cf1c38ea12bacb0f04ea8cd3b2af9cc1bcbc68b7aab1b912e696ddb31bd46369bd2bb20c29421917c7487a56100ccfb505b23978012119c7b035166febfff43b16bff18ef092b9b36c9e968f6f59f28188c2e02a4e7f6e8ba2c0974ff993a3d8b9e178a7942f141f9335ad66a2caafef1d202ba36bc28fb62698b65d7a006e504483374099549494afe360f04c8beb0013b45e4543465d5c9e83bba67aca1ac31a6ba4fe31fc7a56bc99809844bef96048f8f6df8cef72ddf0f9ac2feded7a08ce8ddbd95439a5eddbd4da5ccd9fdbbf4bdc08d61b7b24a6de86d2cde021237b825fe9c02319ac269625c7d5cb96887611e943b6f3d1458315e98f64b3f87e5f874812ee576d72a26ecc8cae3bd7bd81ac7fd4133e47ef367076d2fce2446a9a075abba123c1674e185cc778034b2549f749e98c7d816b153095dda801d0399112194d1c3f44e0d507e607d07aceb4393289a043fc68fb873641fca9e262c1609b1882cb98362b84d0fa71688b7190e850345cc18e12cbfbc6614a968ea8f98b18fb21653faa1989be64f74c3b14f9ad3262375aae08de65f5f69fc597db0f1622b09619b40f6cdaa1ee9d6f02e735ca122504ca12f539b1f2a456fcc52797b24df619f69407f00206c5e1f8f1da20428b468824a9310814907cb0f2275bb2fe7e5d3ef4d3fa9432cc3bfafb8e21b7a0ad8821900346b47d2427347ea9abd974f02fee39708d2e9ab7abdb7f92c579e13e69362421700346cd679fed04a6fa86ca8eb5b41b5670f5484b016dd323e403eb31e8f86d69ea853b55937af63470e23444628e28d31bca5949b2c0702f41b9c95977c45170b0edba06a361cef6a157eca96925c359b4e322b5c5c05957947982e2f004e10f305e142c88524178a5d30e376983e0f2665b9128f82117ffbf1f70e30282de1dd128f8e37ff12609b50cd80ebb88c6dd6cd7843f630844e1bd8fc00f326cb05c543dbaa01de46a202f242ea308ec6b6806c68a6ce7ec6b520198bcb3a82d833652fe8ddf6877613b95bf1c1049b846544c080acf3f189711fc8a0558074f6dfc4235dcefe1686f61e47db24c32ecc8478fb7746a3f28bb4887ee1b9a345fddb0b39f7d66054117142a042db5d581374c7de4c20f50d9ae8b83ba09c3b65de6f8d79ff1b3c49b1a8498dfe0faaeb60a27fd83e2d9c560e1c28b7fed1257b1f93c8b3914fe189432df01bce6f131e91f23467a777e57f03ef9f6a5240c575424e6d00b484903275f273ac1fb84d7fb1fc489a56c2c9d6c5a0a5399fedd5ef15bbe945717a1fa3d16380c9846925547e25e4f27e45c4a32f97ad727be7f0a89f0a2eea4b9fdd90d724fe17f786cee8279c79838145d9c44f8ab10a1ba795a8f9bbe77e97c1a7f1797f9c9f010f8d522020ceb9b84c9131cf0706374963b16b651b6db87cbaf0cb667c0ec173d1b1737d83d4738bb52dce80916ff48fb27d1a2a8271e208142bafcfc44a03c1087080687e400e601efb6b405c6e3dcbbd701120c79f791b1d077d30cdf1a1da5ad6733d2203f886e2b685341e3432f9cb8033e15354f235dae88026f3cb6f845227d3720f6a1dba9285e5f84873531ed4ee3f3c48a51b1eb670efb7b4135d210cfedb60f8759edbf675441aa8f4455ee47dbe7355da720a02bbcf160ed53b0249145f4acfb8a252efee5ee554a5c491f9a770377305cedcdd9dcd7926fed2fb56755f53a0fbd3528d7639c6e5ec093e8a25b4dbf23b26d6e8165de57dfc4e9157d232c19bb0bc03189dd7513ee25cf075eaba9a34e59f06f7e20607ddd7afd3757008888fc87d12f3430332e2248742d3290dc3a67925c523ee2291a595a99bd7e415f8776c035f7014830a01ea484a4c59bfff19fd344123bad88548e288ee4bdc1df714c7dfae404f0aea6ad566c9396811fdd2a9550922ccbee0524d8265a469df8feb3f4495f13ef84b15a0a0c05fc90581563faef6cc02018e701cd4bbe485e57e26d5a6df768df7fd6acafa0dc92517b2a7735fc0e00db6d96b20fc56bf39a31f58b6acbf9d6707d5cf75c638d9fc6eb8670e40bbd83c662326d4772dbe5f6166bbfd4c79ba9d38c5e0f38bb849de4bef251318d4ef79da03cf110e07e05c5e7e556e5248ff9a224c6120513ff38cc8a5f5dd5dc542b9d2089dc14c4584c9bf07e52632ae6f2b2252dc0f6cc99dad7dd3c2f3d9dae235ad9bf7b435bf207dfff4fe97e280e2f7e06b0984be6c32b3ef5188fbeacfa98a245e22e54a51f15a18b0c061720dbf26fc3f8b368c9a55e39ed44a91f8772ec5dbbf4362c2d405636edc84a7bf3f0d0ae2747c7ea301ad2c429cb6995176af5bfe18403d76720472b5b6d5ca5535ea3900445241d6e168cdcd04875fdccd44b55474aecbba43a2abaee4b14c60894629516b4ba1c4211727796945f9220b8cbf9aad96fdf9141226126ecdad95d26254d7264a67630365afb657a665677c6998966d6485d86d31b1c925c0d8ad65294e3fe1ca1fe85609c6ee529adfcd0b608ae4d9a4e5f579d30c80ef7670b7b81c69eec42e73d3f4230f10d4f31eba0f64ea08551fafd7f7637d6b5e18c31a55f191bd5cfc43102c5640e36608982883c5e879e08f7a634aa96908022d8d38488801e022c33e331265f432677f7c781d72bee5b2c17120b3c4112c4f7b3f86eaa5a524ec670691a0f72844877fd90bc0962327a187f4c587dd8fc51937dd98c161445a1a393baaf0015fcab1106bb53489059284ac2daf7320ca388ebb0f01439a281868cd00e186505af296ac4a2cdfc4cc17d78e3a0a51ae8752704a32c276329c73581c9cc8ee83604e46f1c22c1b9c6a2410148666227f93fe63b740cc786909bbdb0d8cb20fbda023df67bdad2dc7c74745a76a56a13639c1c06bf4cfacb40f3de5d73d3092ab9a49cf2eeefb659ab232128189267922030c6bc6037fc15239f055d9b9e9d5d2f601d942be46b93f406581732fc762d69126098ebb15d60cad7e86ceb45e48d2454ea9e16bd60748f086ccef3f913a58b08dca1524c666a127a1c6ef7b5e201f4a133d2d0646bf12c62766e0f249f1f96cec823a29e240ba66e166eeaec1e99c5dd386174859400a777c358caf605b2d2f3fad6e910558606cd8f926ebd1828584ea341f819ab083e96e55e4372c01ee0f0f61841dbc60b6d8da7ace844cfd6d19645d90cba8ed4b07d1c55185168e651719a0c01189b717423cfd92f8b40cbeee2f36d45ab4fc0a0af8fb5496d46351cd39f0f2dc49b192ee919bb75f78e9a8bb9a12a10b11a06f7febf9777993510c1a5f65a0fb2ba7d471326494cca739c54d72256efabda6ed56916cd125f32cacd10e911a046c5dab0c952c1150c042a2ca9fca1e060afc8ecb78415bdc00b4f0fa150e11dd7163ef1ed6581a69d2034a132e67d116425c329b7e236f6d672422d3de7968c27eba4dba0e6d0e2e723cf906cfd0d868954aebbcb6539a61925ca375eba092f5e129a2bf2f1774472b4127b21660cfdb146285e5c95d4ddba4981699f545610c08dd22488ad00ca271a0f7a7f46128f8d157960d757d198058d961d2b2bf581a2d74649e11cf490b8287aa206de788c2b31a265b33ab8f5a5b57ddf3bb063b9a99b84f15017b094a3628310e97fc77a7702568f5f4800383f8220c22d2dedbaab7a43a36aa65a37a36aa65a116483dac5ae623f8cbcdb8891b700337e226dcc04db8891b700337e026dcc48db8891b710337c08d7b88aac33e350ad57021f841e54ef50e57f129946cefe51b870ea6dca551f5135e33a1642475b3fa2cbc57ba60f95147dd2202dad3dcb2e4b6681b201c1098acac51ba437e14fb1687b8ab39d9af6625e09bf79d3f5cb8c61ecf3ab0e8f870e8245a3d99eaf18f070191c360962b2edf0b709f460b068222d43867872232336fed3c0254428843440c5e5210558f1d8ec50551aab15fc3de84c2cdd84d29f8812ea58c1e0dfeb90c061f9ecb3611f767b1a550ede02bd7fecdb06ccd19db295be0f10eace92840e00bf3cfe1f264df6a027c0ac1f5e9b223511c638dbc0e4f21b307b6b7f23fb0313ba084e2ee0ee5b660da2b66cdd55f7d8cb5fcbd577d07d8fc7c4158ff72a7dec17fad4039a59579e28bce8cdff8a1b5d08c3f9577c73d4b8b2d5816567897a93ce88e82527382e05abbefb65cfc87feffbab44a1365003ffb8be3cb7eda44c7bea62d5a73b38f31260410f5e8842b4ea33f9a17f26aae2ad96cf8b805d571323fcfe31e4834233a288513ef8052eb8fa69e25c4886075291ac5bb63929369488125072a8ef5f247b7053798daa05de84e76836f1c46bc872e9c749b0ba7181ce12673dbb141c187ff65d6139563c1ac9e2a007cf6e3977afba0daf5726732ee3ef34759b0b4ca6521a8cb447a18e8c885a3f2da0b0330088f9365415b269e17b238741e04729e37a054609bd4ac2bf521364e464c1d546769dcda565932bf3fef27ace5e5db346c36bacc0dbb51698357d317dcdba53f9de6680c49ac032e34beaa43a3175f799a440239c1741da74c0b9aa2f2b9a23b65733edc73f21c21907a8d030e84ce5fbb8074ca58abe209aeaf6b7eee3868ae8a621b5add7e1e59c520821da8a85c3bbd388f01ad6dc15f6d474115826d1ddd2b6d27640f6df150026c8684890284029eb0088846197a6cf6c626d69519d832459377cd8969e6db9e162ec788d7b5f3e37933b906b091d768dac5b14563c2fbf8c0540f2e7dd93ea020632f8cbea91f7005a0188b7f7c9ac4bfcc5414de55ad91d1582b58a4986616ea83a57b88fa9e9433bca840c3b76f88b0bee7211abed4841ec4a91706406e870ae836a3cbbd861fde9f87ca82b5254ad2d1c2bb2ed6a8c4a43a7456a3feb0b82c0ecac63ca2f7e04fdec64b1c080c877d21e2cee876fb9c0fb51c1a05a78e24fcc534ba0e1567e173c0aeb2ca9eb030b0a232590d0721a0de89b2e82f3f90a55ee0d46a9253e851325defde43401804d02794c2d7718f10739a01a9367b2c24b5d7f7bbd48c396b9eaa686e69228a25f00b35e56de8ccd9c392a9db62bebb0df40fd9f384771ab231bd08796139082aed384af3d57e2e5fa41c7cf29da7216e8a4fc09381b2493341300654196cbe9420ed9749e6b2d0b2dc0b233be5f83d77ca4ab7ebd515e1336ac99b464c4d6b3cf3609c0808054bd38f00ccc2f8e019e83406c2563dfdb60b8469f9f9ac4b5512fe9623e7c2cd2f75cff15ce66ae01b77af9852af10d8129ea451fda07df113dc86d0d42b8b85933fe1432289d4c202942531d178eabddc784cbc9ba902fdae9c785fc868dbce296909a3fe525c1f37ed30ec1836645b6154fe98762a1536ae8b30006b8c1b3a902f84cff9247dcf8a44d5511bf57c5af89b7e730a46fc7bfa12e43dff9956db248e4e171190634f9b43869bd8189b9a920f4319e7d2677cdf40441b9d92645169887532dd34725af5de7cf40cc931e9adc938d878f3c873c63f92ac6066045590b13474a5cfa9d23776b04dd7329f14b8eccda54cc1dcfa81ce2faf9049d83eda3014af7c837e3b08c5187d243d945f3d0803cb2a54253030ff69509346b668d2cf7d44598e0cd043bd88548e76e32c63f2632945f30d17b3d30c166d7fa84b29d02f288984eb8979c3a3a5ce0384a6ca90de28e2f12631c04917809892d6da9c80be4d7a3781b8a1401262f9607abc233f8f8c82d9c7df2a2f4ef742fe5e15dbdb47237ff9731f44a9ce9589f16c30d54a0fdcbbf7165e1f3519df9e51bf737b119cd86cc12b8edb7e3853c7ddeb5fe22eddb5ed19e6c7f5239b52987d8189c7d991136809b6daf70907a5f5629aa556391d5a3d10ec23d6595dc5588dd65f06753bef71260a6b8d534bd81249417c3b73029756e467b18630b455e9546e04d28e820aea437d9bb0af63f6be0d8773e81745374fd1db7b6b6673d8294e482517e76c25b2775b83f9c29db5af537a82080559b557041f9445d1a0a3e657bf2297e42f0cb8eb850e83384e4e7aa0315dc63240d69dbacf8b66322d6f2033d0121ee401a8f2ccf3b8b35ada6b2f4de3974d22933fb6fcc14f600a1b5cdd4d47909b422f06c5926f0f6dee90d4086c4e10a177295f1f2ee13fd8020f5e827a4595c0b9682f063996d905e44d7eb7f67e8b2eb769ef657675722f0df6b9f2e231680f5767386c7631ec2bca898d7d57c1d1f549c2e4aafad750885ac5226578d2f8652fdcb8ae8e51ef6aab2eb1a8522b98e8133938c1b07e844f42483ce5c5ef3026c4602d19f94dbb085939d5d089c2c92a6a3f478a53e68e7dcc8d4b23348b9ad3aa2ea524115140fb4842525e2adec14a15c52d61ef2237f2d493b3bfd0277067efc8bad456b8e9034c662c324248cb978aa9fa60159fa37429491b1136d9fad636b36f99d3c661b6c8d0d2475d65630bf575af40cd7f7ef1a45db5fba0c4e0319709621139e4cdcc598dbc8c98b85291fd87b897c64ce926e3fc8bc728ef38a6d6229356a090041935889a0b890da1922cb6a331d41e40eae41deeb6d1a53107840e916605e65e73d4c0a262f414eb2468e04bc5a5a7bf8bb1b4f8e5701dbab8589c53de245e43ef5387a88687e0c1553edcf98985bb0a80f29fa08f8e6aca40b1051079bd24248724ef199e54223448dc7509ab3890ea4e48847a8378420b99c1298cf6dacc28f2348ac50e0f5c9f7e1dc137db9b5576c84afeb5b06c98d29cae4c8706a75b017d8cef80523f3e82da369b70336a5f8865eab6ea6feeae4c0558641a37ab784a814be1fd715057013f2c939884d0a1d4b4d75bd224f2677b0a7527043a675242d51b3f188370eb6bd13c0f808c3a0376a9fb84c458dc3fea2494e322376d20abc16a86ce4a6b14fd766b9c102f48f7e555a98a21a422e5b106f11f43fd307e71fe74f3a21cbc897a3e2bbfdb7e2adb26b7b7c45813350dc7c70186cd1b13c52da0126e387a322bc5a0755c4853c4f20e48d19e0158dc273cef04f1746e282abe3c6fd55da281da5eff9e89fe8497041b7ae0ec7c66c42f3481611e1f51102f8c4cc14a4084d10210333419d7901afad75129944a7b806096600f30d90e1a9d0cc2314f1330e47af5091b873cb8b18793598f4d86a65f1f3625c32b1ca2ed4f7540167552965505aa3030c40291981d9541b3130e4a3f12f022c9e68fdaa028a4b8926d93a0122778c844c2f90ce0c25ca95b0a3c4b641eb5c62ad9ac09931c4510ea2d0c2579d3290389a8c1d2cc8a0e89c816e2fac01106ecfa0e8b17d0084ca084b4659ce700eb1b9f44eb413f607b1ae8882a2e81afe62e6d626b3c180a801d24f6687b3414cb88b9176d715547f3b2cc627be9a9d51005c89caa4e3d05a4fb09b75e5e8ab536b8dc3d449876be6e2aaa034c10e180d926965eb5e1297933ebc88518166b2f0b685a11c728758c18baf326dd8ffdda07a20065ad68fab1872a8b718a383387da2b2bb65cdf3b3bae4e8f66045290e9942c4411074a2e3b35dfc7c04a9fef472d040f2ab316a7b552d394062730ffd847b25df16132ff27a3896e629d581534a26496d54be859aab42780f3f6ee36b0c0af008dd0bb4b47b48eb1460b0c279ad67b64adfb70fb894b698266cd463ddd50829e82eaa7e89564cd3ac76afd6983c6858a05d03413e9bfaf937afcb395db1f7207880f8499507d59776c99e6515c7653cdb41c6e0ce1a5e682bf83de20ef1b0ba68c210825cd406a836ed5f9acd4fb2734f53b297c1b739eefda128363c6859d6771c862ea5778aec66803c26d999bc51b757f44a0034b5ae83fca56821c156a9181cac8444c939f718fb7a4c4c71dd577a2887d22157d699013f0501ae5a1d2ce27a64b41171cce4c547b54979cf23a9b6f0064e8407f1c4c94820745657b4b792bb65e0e67dc6422c5dd9a270776e0b51ca9b599856e34c4b4193a2bfeb979053dd68672a7738685b37185314f5f0cacf06c49190686e06de807de5fea8b53e48eda4e25e473d75820d39341f9cc1d48ef779deb3b78f19d9de6a456de823c9806bc88c8b010f8fb25f34eccfe62721283f145ffaff393efe74bc38db498f2456d21e99e08dc926032f9953b3119fd69b9a3e6c188b2908d2c2d20167976698b545ae115d7a9690b6b31911c85a4c1310d3b182f7ae77be9e7c1780412f63e46ac0dccaaf900607b177bcc5b2400f8c925213689f491d27dfb3387de4e0d6692dd069a7d468b14407aa90d588bf44ce1c44ac547cb28198077a5dfc9d79ce3299d0ca6e031433d1cf95b2e8076f26b93b9f938677e16e042d20e462477ab0feb4e19ee39347188be8ed9378c9807ecd9b8db50893bb7ec27e21746b1cdbaf035b2760b919a55273aed973391db71748832a213e33cc51e9d0851878b3563e152cb9d2487315a9aff3272db0f00d24ad482ad3531639ae586fee41942b8721dd96355dd73f043add1560a07e468826905146c3b5168f93fb05d71b86e8cc301002e6540ab46d3ffe0ceee5479f7a0466f63ccced98bc2944c37f768a5f0e942abd6f63bba51c327d2d237abf805ff495fbb9917595bc67904b11354f947c068bc2571a06afed005b180f8cafd5c7ce1d514103187b0299f2f91d2265a8ea12682237af417cffc523df49bdea0a3e7fd99db33613b47ad0f2781881d58147e6f0b16b5d41c7f69b6ba16c7a4f98f6cbd82a6a71186eb3ecf3c6c5afc84bb81464970825231d31061be76c4f24fba8c64fc4c922fc4b5faec2cd18c80a216666712aa9bcd8e6c6ecf0c6df8a73db5e626c15a0839564385a3adf52eb3d177adfb1615edab02e9094f702cf2373812446e91fc7a03aed9c6ef4037e8fbeb21166d6e12f63dec69ee6f28e0466a99dbcaa42d0e0cf4e2d4cc4db782ba5a90f3adc2fafa63bbcc650fc7c290896c4059f13fe642dcb35e29c63fa12721e499962ab92b8457dd3faa62bfdaa0fd6c26d32dafd4dcd4b889acf7519d34e2eb347e7eee8473731ab9ca39ad86d278fd6e603aa9f7ce4c90ec2985843152724746b228419d10fdc60d048eb736fdc7f2c18551c1a681e9d2152ca2dcb212883cb925638c79290a96d8aeead4ce2f054a824f512f5929572150773112e149cea79644e852c18e1b5277c453796603bbdb17a1f441b97f74dbf64331306d8442c00bc2318e588cdf49b7e7fb946c86671dd32ec295469ef8a742955b205c7a45d00846819f69edde333b1334af87b4f98a41f70a14592b8d18789b0eb20ef480975c58f60aa16a148b642571728c12c14adb25c8cf13c952de0056d24d98b393593b1495f07fe10e3a53716f49730b59320e818743b898c68e057217f13dd6b890e6e5f2de530e450ce3bebd815d82c2d799edd0f5aabcbf830d4e5f0599d566296e2ede36ca13185ba34e4c66bc3285a0e7324ae10733d7b5933fc843a3d64514cbbea83a34fd6e9275539797c6c4be486968c382c244cb035a11ed7e87f14eaa1a19d4b05faeaacd988f562343ed269f19d83b2d8056b3618141975eeb8c6f031a3a8ca934e1221f5317215bc85554f945223043e1362f1c7c3f46d543a2e4e77691fd788de5b40cd572b8f73981bb5c9d55aad5160a3d446b313e7ea2ad8461e4d56771470351b04c58377e5b3d74598e0afa6fbaea1947f726fc1e740bec80475bbb9bf029825ded0d29f74f2f2d971e2001352ea392f284569c6513dd55baf152a934036e841a50f2a6017d5483f58ce5b55030bac85bc266c36010d30ce507432028e5ae8fd42f6bf1e8bc47b9f6d2fc7d1282d1a1cf09bf0b89c21e71444202c1483b7262d2f300a19382d84d0ff4974ca4cd86a29757820e6c0ca4393d2457de019db3d5eb21e115d7b836f0833d8ccfdd6022ad5f0ab8878e1de61e0ec90d183b3fbe7af92b3212c91f54e1e83e20501908777c85cac01740dbcf55204be0384601e6af861c4d76bdcebae0996a771a4e774781dc16f53d7ec07338da4b997e6406f4d67f2e4766b496965546a484387d4d689921fa5e9952bff47d1c9e20ffb7e21b5e10dc647a541c6f009dcdda0cfb345cdced6355f658afd3d9f1319ed029b6284ffd1c422f885093d6536f99ae49a0291b45d0b066c06b0a726a99608b469b02302f64b6bdfc1045ef2783d19c7f3d644cbd608bb0860d4fe04275a289536c340500b8e03916b3836a9ee2603fda518066ab880ad4da1ba0983c75248c0e9a2554b6702075d146c9f21cd119a8c0e765c45fa302491c32cdcafe004582142c3c90f096baf02c2bf1a05bf9ec830751fa33faeb6975dfadee6230820a807a8e6631c093e27ecca4b8e70da68ed04e9db4b3803ef277f10b640122ecad20d5b4a3b06fce708281bcf27b4d7b24a47179c5cc06a6ba1b531daf4006b55e0e44a7d941b94c215f3127791cc55231440ba7d42c4d5c2841e31121186baee20a58b955ad50883afb5e1c561b20aae55a84f60158a21898d8992a2b5ce6ac177a0a7d8ac4cd3d256104ed645964551c723b566be2fb8a43bd401d40a580ad1f6c1bdfe3e85b11778fc267c7bce8a25cec05c805de064577f8828351d352bbea70e4c44edb0d131884cc40b9b52b7a3e5ba477e7422c184098590d968bf2a021249077c83bc0dfb4980d75defd90dc28643a975067334dada5c2b546f9a67dabbe9740e417dfdb034530027de3c327e40ae1a0709d92573733993b82697bce00f5b3f114fc2e2863fa9294931b527b33ab90588e2a5289c9cc67bb1fc31c4223197cc50919724d4d4d229f91d0706e63ece8042496e4ac171a7808b56ac9c7a445788bfeca8b093ba9b36bdfbc2ce59253d52ccda0547c3b75cfc3c5a24820d1273ab74fc928432fa67ffddb226681ad189a9fc68be4740124ed5c8b516d4721d76f55fcce603f3e93bab3200b9f8d33ceeb03c641092d311a9fb549936b17283fc6c8f4c11f325970f736e320534aa49b9c168f00a5289ebba0e03a00c203ca8c68b70276fd99f4eaa63e892e5c9795527b885fef9d49ea508e51caf69caad2dee23cec65e2b52c93a53905bd1cfbfec68ebfcfe39c45a57b0d58050bec6f8df6d5a740c6d537e7834f248be58c0c2df642914d5f8e21dcc62732c50911ecec4c67ee1d89e87bbc275af8b1949458f352f7df8b7e1528523eee1c6493427f579dc2d700391f47276add244bb4496df122fe0204a5566a58f7124ca91e6e683c1d129cd09162aae8357054f2984c22b49c3a80d7756f4da82ae2a504691915219f0bec78223ee2d797f79c4e4639656ed915ad2b4f7f1b183d3b5b77f3b3a54d9bf7b12843d2fe1e621100b9cf2a020656d925979d07f547afd1aaf653947508cd9280463326dd269e3f3645f8d1d509acd778a262e30f88ca0d22c9d438a62ca018bbd6e2e4634095f48722854af89f3560e1458c3c731c8ec55c221223dd1a372eb4ad288ef8a5ebfba8285e6a771080e3bdbcbde390230f5b3d00b0971dec13de5c4abba9f1c470a833814992a5a1c2eb74cea31194e33db9b92791fa2d5dcf8293a4744a4b50f1e3f62eb0d7dffbdf16fafc56670fdd16046aa0c3b5f5681c86913eadd9d2af7138239bd0a6f1db3103b8b028944eb6fe6df5d40abb3ac80ce58e1b254e885088518646c73730785ddd5e330da65aabb0de26b337c55f4df45f5d47c0ae3739381c3b6f0d223a38be863ac0c3f78b1eb376821d4b60d924aff587e4abf4fecac5147a892f374372d3ab545c16adeedd51e19c7e666df2bbded5f1dec4b8b6062519290388f3f506f16098db0eea0fa544d9e1bba89580961c4eb9dc745ed68fc75a4b0f1aabcdc8d5894eae4da542e5d8c60e2dec6671558ac8b92a430f20aacbef8734bad34cea10795c92f30ab568bc890d01e232f7686a60e9850f39406fc65bd2f8282a5b0bb04aee039496a48aa776f6667253b628b2301c1315a1f91f204e10dbe70d0bdc42001e8a6f027ef8738e346292eb09ea5dc65c6123faf939222b0f22d6238372822322b6665ba4a62ca1080800b65af9001731c992161e01fd1aa44d35ea384b95104b3bd7da12a8a5efce4c003512c65741c3b5c4bafbb876c9650c0a08d53b666b71d8f3ed70731f1cb628020fc7d1e67b046495d1d7f1924ff2615271db3619bda4698eb2e02d428cbec6a157d010bcf377123ad40124b151a1b6b49ffc45311fec7493b5076527bf709cd094d574c7f39f63db01fbd5897811dcf90fef04562c1d2961c98e47a55b84be4e925c219f403bfe84ea6ce8264aeff30ebed6d7ad29dd98b4e47eadaf600cf05b7a46f24ab0b5f6bac9c8ad60c9dc777f7ef4fb1745f01b07ef3204ca2cb276cb4d7c4630cacb1e9dcc0a4665a239b97e09f6c1e881a7e369aa2e4dd782d937d86792c36aede5b54983704cd7964f5ebc820dfc82ca9c7099bcedc7674cab10e88cbc2dd8ed0aba1ed6de6515d7837d3ac2f9419de648bb2e222ed7e25b26b4f0d78e398f53d881495d83471e24306feec9ad4da2f8fae36ec609d6b474b72b7e6bb1826b843a2a7d828562c889128022d2e1c1f58ca528ac9a6b84a5b78164e73f9c1dd53b399be78219fd8b097b7ab4063a9d0711a2a7e19afa84a4017ac709d65e8e0af3a26c1b659abf8dd27527d88d1d4a8506ecce37facea4d69ad4acdfdc28c7b8c806b814cbe57da5e53a2ab960f543f7dfd2c3227e3f5fcb7408cc3d253b91c821af9ce5e18c5484da0921907e3e1dc60043c741f157a7b3444147bac81853909608e2e88dd3d34565249883695b20573118573656d374fe05542ac2a89a0d917672e44f617cf0bbb17c45bee229568193015c11703da06bef9e04d6b90dfd8bb0067a4957ded2d796d228d31bfd55a0efd5619ccc6407b21bb1a4f699ce332c6c0761e1f8659183fc057a25757dbc9b5397554e93a2be566ef9ce0515e0174e045175882084659ef0c8a0563f470e9b7900a64bdd1e2365e2804fcf4914de9a64f89f3a21b628899a9ef00921aac8384e54401dbc6ce0a1d90cc9b63ad1ba071aeb0e723f02a7619f8ba3647982cbe490136f676efb1842a1890216de0ab210e9d59a294da067a603b830f6d80891072d81131362c64c9a2f7e66858cd5aa570afcee71dfca7bd000ad0fff232416f8fda47ed284a2e52a1fddba4258cf96d7926e96f643f197246ec32bf429571b0877892555e84f0b340a8a8756ff10b26ef5c4b695e1b4f95ec1188480f85a4f91354603032f80b69f68f06222c7bee24fa13ead9d7d1221f77e6a5bd0d9eb259d6a7e97db392b79c5e308638e419d6995934b41f2a04407caf4b938c1c83d96244792767b8cf8254b9adc03c0ad821ba6535c1fbe8356939f446f93481ccab1448c7189f34af824db890b020c5088c1d5ba4b6fbdc752cfc26abb26fbed54f98e4e52b7b7602d77eb2d10f35681c6338a6ca996150de0be02c8f2876997ebd693f4e4a19c64ed834b50889a2bd28f1c5698c83e5463963db3262c1d4ba72bb59c59190e15cf4505ad206a348e5b58234a6e679e9e0c3c6dec269eb735b9db16110133f8097968a39c5990c528b5a2639e658544e5c803bca7cbef9fe1cd7fec1dfa200dec4fe32e45e2cb2aa353ebbb94326372c0f7b9ea82bd52a69e1799817a56d5aa5cc964dc7c96f0ca675615d95b95864d6b7a5e6c4a781093e8109a1ef24bfb7157dd2e18024140807fcd846583839f907a185acc5d6e445a9fd294f3c119843b049e5067df108deafe8d0ca23cd6e2aa4e281566824090b2021fea3554db66e6d2d926c713d009d3ceff98a3c2cbaf48a43894ef47d8709288add1ae4d1d24d54ed1b11398b1249df3e2e5dee9f415a7a8e73d1a39f4e07dcfc503fd6bee813d64d5f768114a093e1406e4bba2ce79076366790f3227e4cc3311c87dd8cac136204cee515ce6ffb301ebc6b3d0204b266a31506cab44546846e30d28fbf0de6a0bf98af097e150c86fb2a1cd51dfcae5acf7f546717435efa8f241030fef1d834f334352774369209e974597a46f69d8afeac7f0e4583f12e4c898a6a311b4ec061f0774e535c6f0a212966aeeed08700723f587f7d05a138156504988f7e6b74466dbd3951f9295d171fce95c1f4d46b21687ea4323c968dc6461b93c61b65db161388062c18453847c0a407186c5017e8e267e3d48a677b7a4e7b635ae5dad9871dd3fe81576812764688e617dc618ba79ecd6059ee02d918d6e33f49d1d3c0b550fc5119ba36d3985f4a0ef4e160e29a2f6a1033f3ee81c9463fc4c140325a2ffe33f95d9cfa9f6f06a9d156b5538f18e8ceeba4e68b8a223237e3bb2fcdb0843745c047b37c9d158a134984738bf31c517504186e2edb4509e08c2a547e9f6f33afe8bd36222c935c06cc6b61c5182241429c32dbeb7d6507b806328fe3ec6ef8778e59a2f3239b9bb166bce70a0e7da04706eb5cb3429715d2ad66a6cc986796d3b70e98c9faf010904f21f2de37fd92548d082c3daa9dd4a67bf5bccf6fcdb8da8cb268a305290ac00eca9f6d2c9baa03574a2dcc2c5bde392a60640d0630379a8486be69d2a72b1ca8b5b3a258d04b434c9f2199c996e9707f315822aac1c58b881b50904c5a17048b9c06e1e017b0b4f94d916d05dfc19bfeac13457926e6d8bfb4fcfd0b8d378e3937685c26a22044026008037f564bedc3abf283f537320a09c5c4af6735c451ac83f4a97dac04ae8453a5290d1d501403621043550bac5c591ebec5604e26b754fc7d39ff0f494730c8a406290c9887705b8c8b49806698d8c52a76e9eceb93d479d27406ebaee043ceddc6530822fe9cac5983778192a8ea824fe4c38b911df6af61511491f8764388100a9944f6378a25ef56483a92b16d0d320c51eedca661aaf2f2e5baf34f40ff718440e64cae36bf046eaa187467a744c90242d7f4bcb6dda9a32946f381fffd322c2b74581598594c021319faa32d23b3fed21565ca3a9f6eec815ae9062c44ef4efd0899f9e61c711ecab29ab6f335ab45e7656884bd5b5ddcbd12fccc35657d0fb0146fc8e38e8f53ddcc423063e3fb4c08993d2b588205f5a3156d63e7460a9280e4f0bc8636028409223c7944d07ec0bb78369e8b0156f318ab9dfadd5c66a3bf39de0974ccc58ac0aca6cf71c013604ad709f1066b8bade6a467470d06aed70805400f49d4f8979600f4e43312e84789a2dc370da5a17c8f456b78979982b9e9c785b934bbdf02b135b61e3933d0a4cb5504eb732a9f76e3499c5def79f7c87fecf20f991f44399cd50d78adf40aab5e975a4407dfdf2a59c3138125ef4329c79e254163f6d0533139c2f0920a03d0dc8b8d2e4c677652f96eeded00e2960791991d2b0a23074782b4a557a61ed680d83d3e268cf67334091286849cc23b43356aedb670040ac1d54fc6e17b4cfdb339816036386b7c0452a0977857a380fd9470eed7458b1b3b2a9688ae8b8d42fdc5de942a69a3654993474726a0a07759115d6576688297347812a445db6d402cd6474491c8f80d03ce6165015cc0e3c666486bb4a9306c9eea7574abca07dc163bb0c0996010e26a9778830f92bdc90bd242ac67a6e76b021d5e3565fc5b266bb71337da2931fa953073538afcc4122461dee97eb9a7da21b40fec03b78611412e02402a64a6a80978a3687dd6569c3ba540637933c2bdda52aab271a524b0507d75e25968ae7876ed51053695d078320135f5e41a7d20d70d92979de7c5b8fdb1f5b0ff3ae7ebe81410eca27a0ce6278d56ab7b5b781272d46f1bedb520dfc110191e6c05e10d105433dc53f495db69d13e32114f8691edcfbff1363252905fbffe923b49335814fe5c73c20b6d5dc9dd6aa288fd6506fedccdb3c4d80aac5889da9a8d8ba628849b48a266423befedc82da9a5f161edc3739616939f7fbd2bd15320b750d58e10ecdc9d2a774ca273235ae1babf0f04e9a29e6342b79434f4332439c5bb0b858f98e8985cbe1492f99bee12a471bb121c6f5e06277073b9f1457b5718344a2dd57489a76a1dacb547a3f111a0d8d7bb9daf6b3d3a9d07ac264d05c616e0d1095fe012f8edcc4bc34a55d77d9af0ca5c63fac97788076f2abc282c7c90cee86d793d8a183d63484814ee6ae77c4d57bc7516a779fb945dc0944278b46a9167706491c4b70034792b8309b4c1644e3e600fa2df83b62b35a604b96db4a40f9145097e21b981feef70e68176a7c9979b5b8538e17fb26286d7c8a5ca3a7eb718e0d793b08b7477c7cf650f77d4bba7db6a57ca416213430ffa746d4179e3ce34b4addc91a1682c597458a12f6f76110d43d67874660b283209b431492c6b5f12ca25b6c0e51074f3363b070f95a7b5b0717cdbe4d71e231d18f15eabc813db573183e29a5e12e540f9212917bf5ff9c3b0804ed62dbbb25e62efeb6012715168e5292179af5aac6509890abe973dd137f86af46ae214bd038816ff6a81be58f66225926a39b10b536a0b43d23fefb1afa0225a7e05df1b111f025f20e3d55d863961fd88f96ccb24ad34576e5590e5f99de82b40596a2b23d242886d66bc6872e4ff80be3ffba34de3f495ce3494c245de091f1b3e3fcb0fc851573b777773fb01879ba2d694b8a7f825a9c4b6d3fab7944c85db50e8f733a471199882342aec3a60627c9124162f98698145c5538a6f3f937e9e9c3b5ca3289886a9371c805336732bae48b8ae1086d9a4cd8c504682b43575c559c750959a1764ae00de91f5c9900e7e660169f7995d23250ba0685f0edf1a5024a719e9f563ba6a9abf969be472a2772cc335d2bbf8e14183f2eb2ef4835b10b918d3dfd2bc57d14a4c9578040340b1da6a7466a457b2227e4547f191b8c21a3658614888633e29b136413c5c68395c0eb502b7f5f5c14a15c831be818f264b4417c0c44c856c5cd254357c3afcb922c1087af4ec4ff82ea718b8a70f223eff31bb4683a5ca7d94470923a02ddfedd5c6d6f71a000f31e7906b197df539792ad1853651066b5eae97b43e7412deac848aed5f2886574d79829669e9bfa741112562566c8dc6198fd33e7972d55e6f1ac5470f3b947ac90104ec8084fa38e1bc29d6053dbc640174766d8c966b871c4302194ad5a9a12a0a5fad46b3eb51450378ee7a1a983a272650be43eeed18872a66cc5d4da3d9d236eb96cb077000a9d58277e034d86e3b1bd5a603f5790430054966c4693000478ceac8445e4d46a7fe6f10ca524ac6760b6fa2e881d07621fa06bb57514f7558406e952993210a32fe31cf15845380d49782dbad4a5a89d1b3acf69eadef642fbca9b0e396d220ce10d56106d236d4fb8adc7b5cec1e3a859a91f4de899d7be226087d4c124aa3da7ff58b159d8da6787b2ed471ae306f7b31cc0a56f68489cfe41dff373fb3cd21bcf8bbd83875f7538eea8c09d46cbbe30e3312b31c1a63dc5c86083daa4a121c46642496e13bc89602c3feb8a98ab54e40d47a0c75d3ef26c33ef70034f5f9962edda00b5fa0401a6301bdecdd5cf6e2c4ab62898d3758e961fe97c4481a0359f99a268a1df77abe27a88ae53d5182bd95aa16230700482b19ae1a5cec7931d6f3504c500c93a3c18d52dbf47248b84c4e60862283cf2476888a8c693a0210c81bbd958cd1d40ccc11e2c0525703e8845a170a8980ec6d40f9912eee8d777331edbf8a0c07b5005529aa588eced695b2b23a884e3c37ce4991c3a0b3e93bd821d29cae9cb7fe1d6db3ab4180375c00985764bfa6230ece0c72374d602ed91349f6db758dcc55b4cc91cda6d5d9dc817d7bfa0404a0894b85f52d9cd5468dde47235eae0ee5d4a8b1b7eda9aa5718f78a45b61581fecc2f9b4ce2370e257c9ca5562e9427545db43bca87fe3ff406a930f1e02761ed2d62dcff6ad98b15e4cf659be3ed83124d25aa4c4377003d56ca120c7dcee392eae01e9ace09b0172d877d63585671f9d3f32e19286ed64d9b6e08d59d14da90f249fb84b2b23069066893754cb50deb8686035ce8c742990326b406236fd65fcddc70b1f451d064a875d2a3920b707c9d814da469dcb433d45a9ddda0286673d351372239af39007bc4388224d3b983d6361ade6d1c3c7d4382c07fc3ddca48cd20b10846a8fb4d5801943300e4e1fe302aa0654fbd9d1be7e05228e0f8130cb667dfb45c6b47b6f8813d2bb53e7c12c24fa08925dc330886701e77093a64bc02daf7c726206cc0d55da3bc2a2ca17018eb5492f286ba20c83879c7572330dc98a9de39e5548008b1c81e07cd610c8b38043f6c6286998cfac41d4a186ed5608ddccb99e4e7c10b931d653a8095e08f63335c6c63f1b5bfe6208988b839b6277d4fba3ffe008c88126f500878c5690499774f136743d0096bcc815c244a47d5d339f81ba3bbdbe37fdd7fb2d559b5dba0b2d1ff6cdf261c85af487c1a0487b42aa13bbf4b70ebd33a5fb80e469b5d24c3573dd4fad752186098fb7e1d238f8b211cb710003510ffcb67bbdbdfb23ee20318b1959ceea83d4b8d9daada78e5f04911d0944bfb6bf77a7bbdb25b426d7540052a2ce622f00f0c05f7a46cbc1329e6f504e3c87e44748a7f8f9052d4e50b7ff7da7be1e8dd0f33f84dd18a17c49d00e7b7767a2281fd72c53841c1c9c1f49805bf84da51601f745dfa87cb4970c7c2961abee08ebd9b09ddf7996d18fe645913ba2d1e8a2e67ce9f7e722ca6e06fb6a8485d81e44d2c874f22deaf647475c2937d0f73db209e99bc930670e2bd67772224305eeb64aeedab887fbba905713e6ab2e6cb0262e4397cf5f233b602a269173aec60bb7286a4452c7f68a67b9a0250bf372b6ef9243e09dc60414734d2e85e4bf5fd1ae60a6f683008737ee765959b83bc2832c72474beca610db38cc501c3d33d701e1b5b52d4e547704801730ce94b2956f93cbcc88879b456f78a63a915fcbe8e6466305aa3c98ba04d579bbc2d2cf323ebbc6010690fe6e26afa35d8eb19c7d39e8b4f706cab9f4911b45d1e25ce0c68f66685e820e50ea6fdeca9310ea1d1aad2cde99dde6e61ed27b995cfbb86de4d9484d2245770706bd7e7bdfba3fde4e10eae6c26494766617d448fb2bb5b489fcb9043280b3b51e8229cdbc3a68b07d8495343f26d34446bb65ec4a4343d40697d835b45472988f1effbf163e69c0804e0828f14946661d541b3f6cb50e348f6c104a2e6c890ddaa77ece0e035c7355bc6b73c639aba91a5bd9443d3e4581c55ee60db9044775580a5c632bf11d305925c878250c387340f6a6be50b7c01a0d0673ef95aaa4e863e4fc9363e738cd42b0e2d7f2813c8ce59276479891959c7f002c032dbbbb767f0a36619e8506e6411ad30b76369e9bf0b446071d57217e748d9f56b62e2504f16df9e3720b40e15cc15085ad87e94979e14ba993cb9c4c9f032af083586d32c656ec2c8d23eae682738f3fc84c96d756bf4f4e8ef7a25f5783ca2409221bcbc03ebd8d632b3bddd415589f415aa865dd5ff053546797afdde330176d692d56d707c286417e8328c00a829d83f149939a365bbe36fd21d4ebbbe155220c1011fa16baacea356a26bab55f18f91d7ad9153db5f3766d0379c267ff8952f8fd229276257ae27be00040be2c1e488a22a7b6a2f6d044e47f11e593390697b80a1daca2172d0f6fe5243cf90410fb78336e7661216ccf4a18c4dbfe26f93555608363c459054d222afdb2eb770cb5ca94a803268b9f8c2209bb5c23203da5b2e9883928063d6627fa946177300f80f06e73875a73dc9155ea3ee2a5cce734afc4dc54f0f596eb6273c6e3d027aff4e7c8827fd42f0be8defc5c6047a6b158eeb0c22fa176116780e5b3d0283196354dda8996c0e57d21d6b41fe70b09738c903b960a8b9a89f6c22b29c73b100f2710a4bafa22f075a033b8ed9f8516111fe798b933798dffd06ed8276b06c469459463cf4caf55c92b8bd6031a2dbef0105d73f190444f176881a0c42bd82bf14f31b2b826aec3d6e48b353ae210d2fb4fa2d0887358c72e17b726827f3b5d376d3586a62b5f90f6febca2eac50734a0aaade1ebfcf6e9dc5859a53a2cb7938a15e043cf3d4f98f788af740d76665fa9d62c146c36060f4c150c0e1ff8d667066c2630852fb30b29c694e78a8ad666d6d7377b7053d38c13a7a3171384187840585f0de7891bcb6325957004f78af0b1674cac1baffa989a3f30c05de51290533ecb1cee235dc0a7d630e7752068c670f646a2ace55e39a81598af23822f96286a4a15fd22ad74cfb6b69ea5a6967c0dd484833dd4baa7fc656d910c28c3c0fa9a3f670350a4bb666f97c0a391f78865a9a2baaf1952814b5de6017ee6ea71737cfaeb81105776b0b75bf994208bcd3729a844e445f6bb941e88fbcc838fbdd70fcaca187a1109c85a6d5460a0095701b0dba0ba03a15cd91372606f295ceb6d764b3a89fcf4c50cbcad02babbf95558505ed13407499c3d40244b7c36247396b690da40fa1b18f0fde2e2fac82fcee7aac5349667b45d5201786eed1180818d0dc411d71372e62b4ba6e163f1b9bf1e48bb8a6fbf9469a785505544425a68699326a5c82d53923250055c053f05b1c556a9850cf686e9a54952190ca3feb90e7a333a44f62390ba00fa502532ef3cc690865cd9906b3541ae4f95782c37e4fa94078fe5218108b9fe60c3058b852c855c9f09b9fe34866ea15d8baff4abfd3a69915c7fdeb906fbb9c595a2abb8421472fd490cb6f2c09afbf2a4a1b694fb74d09722d74171fb2822d78f581a21d77fddf24eeaf3e8290c5b6ce96828b6449756d17cfd08b34443efa4be44c4daa70f1f5618c54300a00653b0c1a8e56331754ffde7d21a46415a3eeff3c38f1cf928d1b1a555683ca07f7b8135a080c61af01e5edeb4563fbe8c3ba3b5fa13182cfc583f0686301bf952e4fafdd25aad956badfe15629fa6c16e346444080db98ecdd71797e62dd03aecd7af000fd7b1c134e49efa153ff7bcc0d55a4dfd09bb2f4f1f1a9a5fe7cf3a6bab54d4042598218cb9f124c5a6a25c23ce8d2789caee082e980f767b78f9fa67351a8d4683e36bed471016bfbe2e7c27f36365616a06db3f7df55e754b6bf5abdb2eadd5a7ae0a727d7a85ad4f29b57613caf5a5a8d6ccab1803574c6b612862052e4aee832239fa208b1caf5041aa27cfc42a5139a7a4528d199f9a82d5abacf9c35b3ee945b739f6c7fe894bfa252dce39bfb558d26f739c42bce82dc82df260bb7a9c1f1fbef427d8f81effe14f776607c05cb1ccaf62000932e6040e48d6291522e1d79e945883cbba2c89ba47b752555515a6547a7f4a9a2497666c284a75b4421009a56c0bac385441762a56767845acadb5ee90210e1d1404e21591a0e0f134e8454870e16d53612a72e49199b83aac9a96e106a0299ff4e6bfe9b676de348410c28f117e14406b73fe04ef4a4a6b93c219638c78cbe095942b80d6e64aabd8ec234500ad43c6677ec850848c7c6f90fa88b5f91121b2863c5f9a73ce39e77c9db4627a2ad69f9d753e08a77a29f516d93d7b7d932449ffa4f720fc44bcc54c3b4e11b5d6606b0d351cd49f4e92b4802bc397558f9b1b0ba9308ef6f8c7aa8756929223fb9bbc1d391e8a3fb42ef899955b494ab9c0ca5e31c9709340eecda6d69cc1ff4ee03fa4408ffaef156f15c8fd3e71a4b896279d5a6e5c12a598699a84fb47f78d9124646a84bc51261021030c3c4a4d646f220ad9ad40a5265c1ed32afecfba28fb43f8f1b3e30d668f81505861fdb71bf9bde7ed98ef252de6357928f0bb4686ed150f99973671c38367a924035a96192c44cc717e6b71c6266f68cca2480a444552d03d21bc167002d306337c4991244d7a2b493736c6409c2449923006602561a079e8aa07e684a654a8940cac54044948e6e54f5a18b2f590adbf9025e9b7ce0246020b7d1e508a54925e8282ba47b237939d0576ebd7f5c443a4afb5564ae99cb68794c0c697be89f02418b9375268263412aa11973ea65752f316332d5a8b2d6f14017f29724ffc172266189f4e374c52249b9031520c438851c2e428a9c8515691e394a9405a659320184434c80824d3c88da5282303bbd1508e344479d02a1207add1c8b09a328844a2551a4b20ad5dc9b5b6807ef9244a06165291a486e93dfc27035b3d18193e6592a18bd93131bd7fcc09f6fdc2fb382065fadeebf77230e1e003f25bcc39a597f026494992f27140ca9243393f3a68da6c28d57a0cb631edc04fb4db37ade2f4cd900d35e9e2708d89b9e9f766b48a84fb67b44ae3178398198466f4b3ad750b0124a07374c72301f0a6d0d7516aed66f33fea77906d1720ad350c1a48e7004936b05b0301d2a01c2d50b05b03a1b4457004530511ff91ffe33af2dea7ce5a29a4f3dfa7ef6bc0ab220b9198fb8f8419d01ef80960e2e2680d3a1027da6391203728020c82021c20410a5094bc0934e4f8032472f4000c6c8f929cb4667e34a1073d600110700084222cf841911fa001c707994c26d3c11673b0066338c33006c6eca076a0301f55d5c3f5d27913387d6545d16371f1fd7189a7a3d6c09b461323060dbcdd9b3d9ebc4591c885099e70852f4c3bd8620dc6708641201008042200d52e76e6f0bf79ee6f17eb20f94da3a3e4ff9560cac7f3f493548a35f6c6d83ca65adca36950c6f0d650d49c61aa058381dda8a8c5ddddbdebbaaeeb3a8ee3388e6b98869976a0b8cee7e87a89a276b13493a1199aa1199aa1192aa2540ba5d66e36ff9af6ea6f29ed4ea38846118d227abdcc79bdcceb655e2ff37a99d7cbbc5e72ff9472ca29a79c72ca39ea7eef9c526b379bffe85d4a76ae3d25672afd57c9f8afe2e0f74e7c85f228c9495fb5cc60a908be8848e010a09fcecd7c00045b0866a500296f434805c8bc8940aa1430f33682fce24f74528bf39cfb3200eee64066dcada9b8e16e1dc48a0d8a36777b2318777bdd8bbbd1ece27676b7e8c416afc8fd9abb493bc8fdf66e5216367944ee29b659c47c22777fe66e0e646b2a2684a20c2d0e12093892c486283c91822c98408209982dc0f628c9496b66a2aa2d4c13e6c3be9fdec57c5c2db9ebe755ffb2dfac516eeb8adcd617725b59c86dc5e4a622f70433811e0b12ad72c4db4183c792f96a024da26d1a927bea7650bf4d49e4dea6bc4d2037f24efa290c181abc590cfb6dbee4f050faedf52101eee9a797c78a7b52ee8deb79289ba6324991df7b144fe565ac78f9c15723a7f957f5e0f06aefe4b58a6559d81ab5d653e84ea06a84dda650eed73cac2e0ffd99f76d0aa24992f4a05bf07b80188977d253a4aacbc384c44f1255dd1e9d8568a9825803f008eb27d03be9118410425855553581e08e1184371e4b07ace7ed90be5f7b2cd6f7e36895e9bbfaa6beff6d8e862b727b37dfc576e7905b8719c43d8f8a1c81b44ac6486bf1054f257386e79998d10c727f0cd1d2f29922f7186995d975e60c4f651ec1058c7bfab35a2ffbf00ac1019a2190d65a25c63983c45c98297d178a95f027c27e64fcbc2fde8508fbd9fc0f6f43cb8708fa997f5d17187f7d75ebe5e887669e47c3b844fc07c66f62fce6655c1722fe535f4646c69d8a7839fa63dcc9044f87fecd9d7cbc1cfd306e860d4f87feeb66b07893110fa55fbad30b9ef674d8a615e4fe89833b88782c42e8f74f2e2d5d8089399b6943260b4800ee3fa32e80c59cfd50b863c22e802ad3f74f32782cf1fb27144095ccf74f2c782c42eaf75b57c8fc17d6fa29721d999809486b47782ad30b9ed6df788a26d04beecfc0c008c1019ba5187fc1936202d25138153913c3e57eac21cd6f2f473ff5afcbd94f855555554f5babae8bcb0f78e4a3447c22e8e7c73c72e4c807565f4d3d74b6708c57d15a7cf8dca74b921b27e24b0f5b40f8dec88a7fc8a3b52f58c72badc16f9cd2da64857dbfa5e423fcd01a109da33719a584ff7e7bef436b40fc0044ab3cdcefcf9fbf87b7f9405c1f7e78fe3ff800c4731f8090f0bb13d0f9e0b82184f0c1f8d02a3fb40a10de3cde7bef01a1421345aaa00379061c9b1ddcf38cd651fdcb404aa9bbbbbbbbbb53afee04dae34f371b7f3017f0015a41614a5ffd1f2e40f1fc1f3cf0c3103e4418a586ad79c16ecf8a0bb4f78cf38ac9f54dddc3cbd64fcf3573768f21a08b094e309256107d94c86c00e617df555f6ca82680d3e3bf682619bf41188c71d5a3213d83ed0cab17df512ef13cf59dc8b505b9bef886d248ca42b638f653cfaa87e667d563fa57adb56f37c9e5fad4fe0828164093a2268ae90e9ea72e912b97e9906e41aea0aa1242a5a81e916b4d22cbf8ad8672ad1506b956d0d54eb9d01b24bc27639aa02c8f080521cb2472f5411ab9a7ca16f7d49fd228d79f8cd84d1a49a3c702737d090b1fb9e2cd16218dc8b5259ec0c221eea9f5a91a6c19ec4643a12bb6079a852fdc2e1e00619debdf05ffc598d26992524a29a5537abdccd168341a8d46a376711f8d46514836d190524a2965942449929e8a224cc3b92ce79e739e8407c1662c9cef8f4cc01d9aef8f166b1ddcc93a9d2ceb78f74efafd0927e245327c3597122e293a1aaad1585362730d338b56b18fdfe5fe0f78e4f38feffb947447fbef3f6f07e7df23e0a960ff2089e846bb68341acb031f00c110374058e7d2607bc44f42f23ed7c64791a784c4a32429a5b08f71c8a4198b8a44548b24499224491e638c31c618638cd18462e1fc7b10bc1d9a7f3fc453c15efb0d0221f9ff0d824a7e832d8f5abbd9bcbfb8e742cf6c50119290dcf781529e2495dd2833d11b4a6f4e32634511e7c625de49bfe64626204a3f766313adf593dcf729b91acbc1beb5ff9f708a8537edc2db2677f06635d7fa7b6dfc5f8fc743512d36ee8db7b4fb63042d9f1bef993a529acc384a5686baf7c66b6efcf572c164a4e82de19b66c6e2f14e321b968395dc20c1540be5e3b15cdf4f9500eee87c3fe5d22ad65383e27460638f92522d251dcbf1682478d2a818638c3136d542b5502d548b46693e3f22afc8c96f8f0acfffb3f11e0ca594d20907d5d2988a688e94e6ce3c49949c24a5b992e671bc07c74f95d2cc6966aceaa9e8b160df4f97782c26df4f99803b9ac0eff27f7ffb1bbf6d288985a916f774fe9c5c1cd7c62db913beef6383c2fe7d7d2c9d7fffe00efb5b66a3b4fb2e25ff247808154d3428ecbe9cd5a05ec67c7828cc070af58cbc2fbc2c3c2abc29f2d301633e5914c57807bfc5ef63daf3d37b0240b9bbfba41567a6497d755dd5da48903b96a379487009d542719989aa4a4a7eba341a8f099c6e7579bc93ec6fbc76ddedc5905c7b2b35fd7d1f8bc22eb52e8ac46a24f5990b172fe3fb3e5a8ea2cadacc45f662f342868cec05f537c60dd4c798c1a19ee4e21924243ffdbf76dfa78424c68c199ddbc12598c6a44129a594d239e79c734a29a5945292244992a40ec626354c341b1a8e89e3d65a6bad95524a29a573ce39e794524a29e58a2449926452f5986c5017b787baf77da61b271409c62185c22457520a5f1b2454e4d91bd1418739e79c734a29a5941201ad7df23b7931397b2dfb92ecdf0d0a8714aae4becfc521071da87b6d94601b4f62e3a71c4a4a7eca91a35e99f324f77df06bd09c73ce39a594524af968aeef24fbcecdd84bb566e396dce75300280d1600ead23ce9406177e6290785afcc7fdf47ca930a85dd98a715cff8fee81c29b93fae2347dad0f2f17c678c7f62a1fe7a1ebb30dffb2308cf5351f61dcad96f74c88e9ab1347065cddffb3e7fdf07bb2f97dcf7718ee3388eabb5d65a2ba594524ae79c73ce6982374aadddfc6bb27387682d7b7b410051b2e7dc0fbc93ec3d377b0d48ce9ea425678f2f97b318638c31aef4cacaca0a7661ce2ecc3aa8ae416d4417d13eb0b8e20b4fc78a4b5688e810db6d5e1e46a3c263e6c8dddddd57382b6ff1f6bc8099c009cb388ee3382eab4ce0845d150f0d93cd1166553c34c8478e858f7ce4231ff9484a29a5941cc7711c4729a594d2893186332c49922449528c31c618833062c44883602015f2835344f18413f93d5ce2e908224628a22d96db00799016e47a99a3208ae8608b31ec9c6704de20f7af8c38596502276c62a1ba51bbd839ba5e6aae3af7f453bbd93c27c319766e8e26167334477334477334e79c73ce5a6badb5721cc771190e8542a1508885da41f928000563ec6f300493d8e01146541f783a60e825fbed8df21389a2e87a8121e71891fb88dc49e4fe0ea67600436ff106a780f9b073e49e7e4aaddd6cfe352de3604d8cebd1601f5d2f5714d7cbf572bd5c2fd70ba594524a33994cb93f08d7314707c01f9c310f6c005c00bca1842801f046ed0e78b31b163c8015bca1e40d8674e00d4553c19b9603e36d43039bdc1adfa04e07d40175401d5007d4f90da573a9ff3b3f0de3d5575ffd86926bdcd9bd931a5787efdceaffca8f7396c5599cc5599cc559bfa1d4b801f8ceb5feaff4f1eebabaabbbbaabbbbaeb37945ce3e6f09d7bfddff8f191eb78ebd6ad5bb76e7f43a97153be73edfff5cf1cf56b5ef31b4a8d8bf29dabf9bffdb95ebc1f0545d3fe6b5c1cbe73b1ff0b3f548b67efe2652f7b194ace7e43a9168daf710580e39077d2dfb9d99bdc4cd6e14eee9df407e0ca1cae4cb952cc3be947b952e89df4e370a39177d27fdfc7e427930b809f20657267fcd494c9bde127a74cae8c9f22657263fc24512677f393a44cee8bf968b568e0286a0d860bec5bc2c88adcc1b8d17c59d3b54b85d9ce65bd9e73ce39e768341a8d46a3aeebbaaeebe054599889c95459d8d5b11c0d9daacb84e2a9b2ae2ceb588ec6b3ee092245baaeeb26aad268381c4e3669eee35c987f64dbf2b4fece095fc277e049bc7723a803717777f7aeebbaaeeb388ee3388eb33419c7ba320d665d1dcbf15028140a8542585358a56457c77256306b379bcf3417631dd7ddc93a59d67910852b02052ae0388ee360c3344c4fd14fe828c058d7045bd39db71835b49cce65557688c60ea9ec10cb0eb9ec908e1d6287582fe47ed973ce093529179c2aebea9e205204771bcee2163d2688d9ce6505d1eeeeee0ebbaeebba8c4e957599601dcbd16099bbbbbbbbfb86825df5c01ee35ee43498ed5c41c05899c009abe0545997bbbbbbbb3bcc9d07ba278814e9ba8e4406480281402010088a5a6bad55ca593394757520108e31c618a3bbbbbb4f00a030dbb9421e0ad589aa5cd46841e3858b5a6badb5721cc7715c45b5cbc398d8826bce39e79cb5d65a6b0581402010a8b228a59452daa1240c0c0ccc13d55a6bad75566ca5ea913dac300d86f9f0289e8a1df2b4fe270429ba2130a12020e7dc4763d157bc6f2acca6c261dcddddab0ede365707c31b4aee8f59655d1d8bc1188a31180a6541b8bbbbbbbb4f5ce72b2bb1235159675219a5b2ce4433d6ca3be91f00cb0edd13448a745dd7751dc715810215701cc7719c0b0ac6a4e1d8ce65c1988ea2510c1613131313d32d80d5c804eb588ea6a1099c2aebca3a96a3e1d84e09c9fc69359dcbaa600cc46262626262629a526b379bff8c03a72ae3388ee338eed260f8667884efbd9ec7b8a485b3d77d1712ecd4becf0caa61628d16345e7494b35214a594524ab592ce29a59452ca711cc7719c4b83bca198a494524a4929a594d2cc14e79c73ce29711cc7715c10e69c73cef994524a299573ce39a7bbbb3b7d41c1a0aa1e19acb2189c0c98289e70a297e81de4f79dc4d301434f7690d11149786571581445511461189c2a0b04cae69c3383b9731803b300b500abb8a1b1d848f34b737bd758732d4b636934160fad84a47b82881769154bd2755a57d2751dc92483bac1c5e2d8ced5307d752cc7c25b1f694ab3ab63338eed94649cc9a573350c8ca239e79c73c2c07430863992fb61865d0f4e957575ac06478dc6b2f729e73cca5929aaeb388ee3388e9372d60c655d7304a4ba94524a29ddddddbbaeebbaae33895dd7759d94524a2925499224492aa1e69c73ce29b9bbbbfb9c4161b673590d7a0db23a163b07c3aeebbaaeeb32ebea600ee3388ee3328ee61fbf0600aa71e7ffda787c3d53a43292cf269549d4df1bdfb141e5ccd08cd530efa4bfa7e0dc7e82e676145e63395ce7eeeeeeeeeedef5d599301fb0eae133cc7e77be339211c6b1262ea0bf187798ce4567d2755d570698692c07e29f1ba8a4909663e9d48c00000000400073170000180c0604c341013911e4b495061480094f7c545e54362093d123b21c06661c859023c61002002000422233da062b05a45310b872d17a9117e5540efd0d79c52a65a731c8eb2b28af7afe7831e26414af4e7d75a3fc40f4c5938ba43de5a5ab13b68489bb852ad83dbde6b7bb20fe4c0bf07f939476571a5d44b082c45c80c0505d9ff8b0a24b71e890d6240394a325d4622c3add16c3227423cf07f12453fccc3fa9729ad7a8bdf95981eaba1f1a8db890aed116f6cad8adb2e11ac351d71135b53f20273c87260e7fbc6dd931b46ddb293451465d9de86e15036149899b09e2830eead782eef1494f11efc8b467a099823449b64e89ef45043725377fd7f05478290e972806ff2f6043317e7c71eb48ef587134ca4ab7878333405414739ea34cb5aee4ff9bb0f20db6ec7903aa5459d22780d75dff83eff30ac8946f625f4099e526bc4a033f281f0158b0d682a4c1b1910124481885319c984f7a5fab99d34a2373017555c93c7baee87049033d6c8e4355a6392e5717c414cba66bc96ebbe3e32440534477f54770793cec413e84218061a432feefa9c862198bdadfdb2aa9692f2f725cbf375afbc92c023a64ef6d955f4e261320f5fee91999cca89f9505a6919f3243dac4f616fdbbb4aa987e35c77d815bf7fbb5b45ad7e21b07289d7423634548d7353b839e58f7a885214f5965b0871296f3289c1a0d389e00165775c619c0a1d348b757d5d600962491663bd1c75d8eb58f838c6a85f420d80950e611be3e7060118859149067fbadb5e22d3d80688a6e9dfb63354f93a2bf2094c695135aaffa25297e80f536774219a481e4cbe3e43e7aac99c979ec053b1b81676f8383fc04753bd5b50817e96db4e5124c0f102a9ab3326f924a574959e1929a522695ba802db7016603c998660d6f10db51bc4ca71c77c5d3a25828c5bd76fda1d7d89ba9ccfd713b62f45db07e936aa0706c3a674b130d86c05e3021d79b678891de120294d12127194fdf24cbceb49a20cec3f4509c4296a7d812197e61d666192fe78542a3e02a4af4eaa96ef2e2aaa94d69922a3db311fe6082e0f564531889bc1473591218f8c34f2fe23549371fd0c442014a3094e66f843bb57e719b3847a050b19fb6e70f4fe8e2e390d29ce4e1c120986228ae0421886ff8651e109cc890f291e1ea0955f039108d9223df16f062a88943e8cea4ce0421d454fdc3c79d3ec1174ce4a6040658a01873d21319c23cffa47709d0ce0c3852a5e3ebf1f817b429461f0dede3cd896ad81cb26e4751e5f127bdbbbc86d4c95244874d67417779ba2f574909268d9a811f87fbacd2e75f4dc0a4ed3038e70403de77287f227c5a10bde843f302efaee1c6de5ed08e9aadf093392b4d3089136ab7834bf2941adbe0a4305ee85f096aa3983049dc84bd5c4f10440c05f37d5208f033e17439172caac44b6e54f82e2142a100bce52c27d2f09513ce03af4c4a5e9c05989a791d315701b7800e62631e1cef19e457c690f1d20bddbd9b066080b1366ef6c30e0518c8ae53d6a687d9603383e136f0d0166b871c6afd19ea8027cbdaceb4a58152a33606db177397b97f86a7adbd746deb99de6e372089c56bcf0a7967384f0ccc74a878bee06c37fa8c25ee6d0512d9471ac596329a742c0aea251c38a0704292cedeeaa4182a24cfe2c8c0aa9882301ebe6c62d63ffff9b55a7df96579820e622ceca65e9a130aba96b985b4dcff42a51ec1bd725e45d4b83791c4dcebd5726c0afe578d45c267f23d239ec4e1cb7d9b5ff2992df61960fa1997fc33fe177ba6c97e29dd36b20434c23a0f597f40a6635e833a490df01e2af2e4e75ceed4f08d3f53e47aecf049b2ec4921fbdf6b9b9d92ba17b76fed5d48b4e663ede618206c5beff5fab62866533efb283cc251e696d3c4dc6119dde38bcf46b623f829d74aac1a9da14b8c78ba2ff2b41c6c432871031779f491bca43907048f39f71e464ce0c64f7acf04ccec3ad521224ed93a353ae3d5e5edfc70ea0892103399bbc5923bb64a727fcb2375645fe4de1744eeeedc8d6ccf2b68ef71072453d37da244cdba474f1022b5b51e436b78e6948024b5e259d4f30eea88d79c704887a161577c44b77696f2a99ab94b68073c3df61428152fae6cc371f7e85cf93d4c78854f00ea977797e829459e0b2743cd222dccab11afcc00c417c8932129eca448f809faa57b50b174218d2d9a3535f44bcd4a7050a132a3ce99c0ec228e827e408447952dc211b11c09f3b67a240cc7784ef447680248ab820275793d8573cced684bbd2e33473d9a04d9267d49f621cedc5cba4c8c6697a726b8126408e1d33b90eb2709fd957ff9c06e352092962a7f1e1fa0ca4b642bb3c0fb1b32afb2243df08893dbf51e00a4c789cfebc86f4d4338bdaf57446f669dc0397e7a9f3a8314818e0ba0a591c87546f25eb00fe7afdb77e76f732f8f497b3963af3b13f3000d8476b3c632916f925c3079d9fe968c86a8a93195371d99caab16921d411428bb2e146546a4e893c1108da9d71df73fe9bcbe8517d953d7c66109b0dffc02a013b08b6db81b7f859d00ba8eda39abb39e249ad4aace17c1a916afb498ee4e654f556976868f06b58a249495530914ca1e415fd7cdefc2779962ee6aa97df53ffeebfbdc989e9ce3d8b0247ff37411f2c67077b484171bf1a2d9746d44684dcfd63d7baf4bef0a04a05e55814f026ab9cf93b841500df3d74178fc8e81ff9bf7dbfe31be019b02e1209e40155e57e3cf2c48c617cbc864f3fce33db541c82c75325821f469035b31775973c936bc95316144392b6749953015a9c48b052f05fbc6cfcca1d5a8a8f758386a86fd913aecd4636de331f5964bfe0aabc9ddad74551dcf7e62338eace9935428d007bb4b678551ba2044ba141e21c75d46cf319a6b999f36dc63510d6fa05d787768bc80452027379132646f92dbbd6ad29bb8e92621645545f1ab8b23c357c49619ab50ec8b63b03e618160ae0f280d796dafd02c343d288db86597582af40e90315adf358c52e0058aa02cf0a2b30b587fddac4fe82cadd0e2ee47ae0f8a99cf186bfe2c774e240e387da9f1206c2e9286bcba56c824361e163a1c09bf1946ca6fb7ca9082039170ed1a52e3829064f4351d8c50cacd725923c145f848e34694b1fcb885783126c5e4619555090504cf0a23df3ea9998cb5623e872c3fe800bf848efa4974a4ef47c77b413ac65fa03563629f4158bf0e4a0983503ab8ed6c0cd74ad1cb943e4aa60ee7755f614915fe6f2f08b01eba006aa8d8d2ab7950b2cd0485f09a50e001e51a816787bdb99f000c149d811cb0a8cbda23055b1df746e815a72d8f7495f1c46182e7f2e45e7b737e634685dc08c6a77ea9a689d9528d2121beb242dc2e5913f8189eb8f645f6ee218f6b06869664a9cb2b37af5cec0f6235521aab335b15749b29039d13207b1122cc30cee8eb186f2570115935d43955dea468e2100cd1f2b437f3f78cbf5238a0b7a1f910dbfc6baa7c2b7b7e14f63087d428c384dd53da95a7c18af0bb799032d3b9612b872fbba642758140d66775261258e9aab125b1492b0f76123e541e9225318ffb479e00742a04cd4e69ca4237d2b50ffbd737965e2eeb6a612498ce97dd237f337d7901eda4531c0029717e25568d54053567752369766790cd9b7b74f4eea1c4a7255fe23ddfaa5f9df5a6c98864baeba6b3c3b0f85da785542c9c759a3ff17b0d9ece4e2aa8703cf1e16ce719888054719b41b273067706fa51b1b647640ddbacfd9a79c9e412a9029e6c8a9759bb9437b8ea642d1be911411fb9ae6d175d2767f9c2202b57c1aa900654e68b6a65e18aea1075970bdb7cc9d5a3a162d3c1d4bec67701b7d45e0551190d53d833908397d3322455143afb201a7a07aeaf2732d017874ca952455f77acc7fb693cded9bbe3fb221d272d4783e1e7a590b65f423fc811152667ee133df3f9ce7d91c3f64d7fd6f7d88bbe6f94f32dc6e54b17b92032575935723d423c52d86030b01124b65d66e7fff161de5fd7e4e19d06bcec6d530229259d8250753bb537856778a2f9178646933e68bd63401b37fbac6347cf0ebd16f054c1b9db12ce611b3546228aa82a1466826970c9f2d7a4f65b8378adbe8d0abca7fb879ee7becbece569d0de13ff7534e0a9d299c8f8dba0d629aad6d73a6d686bdc899181b31ec6ea0d8077a1e32fba13f2872da4fa2199ef2fb67da889b3eb7906458f22b45c5ea1966562baae7ae8bf45dbd95ac35e99ab3466c2bcbaf5e230dcea05f737ea850b31d30be8e4d18ba9842785a5c9dda9f5510d3abbf361ef0c33c4dd139ee54463918cc0dbe09e8b321f448e31c8752e1030cab9301ef0e6e2968912e5da07cba361c370d88d142caa63347513762c521aa1b015712225fb1a0cf68d4d5e171ede9ce5ad34954c5125e3ac921f61258f50b320b7922f6759b4b99221c55958bf92e006b330574b4ff1fb4f71d859f40b81b0173b3da98bf5b0508005324509c288fdb106eecf32d7524caf850fc2284cffbaf9ec4ea3b3d85e72d5645d45f9c1f4a3abb88f2256ff8a05312463cd2fb733fb09feed6ec742db8e9be4768bf06e176af5764aa66f87be0777efcd32c3228ec751fc63a7d783bc80b4cdbebfef236d19524c61bd62782a943634e14d78a0d836f8c63837271dbcbcccfecd1a4932d2584eb2d2b3080da97965d4db7106ec699ac9b814a1755db1559969ccad7de18e9d74206c56dcb0a0c680e8dc71891d518d6813af1aff1455008483eb06af906714b8982c52ae303ebba49e3641a343e5f8ee2f5bd934d7ad40fb352ced2c2147ec83758cf9b67f91acb86f34da2ce325eedf94a23702e5d2f903804289ebc3ddb89e4468e17925701d53b69963846dba43071cc6f913b94cd1589ed4915cdef143e1bc7c04b06ad9ca646f316c23a4a90f3cd8e594a5c5b93177289e4010ebd83a5f99d80e01b5edf47e074e09cb6791a22abbc9d1af7553d720adc51b44c83bdbd691f948c0ed4b4410fd0122840a06a055b75deb89078b14a8c1d42dfea1d5e922d54da414c3cc07c627024eee97a498b5d1a7bd7407dca537c2310f3d9719f481d97ba23b85cd93b69018ccd18779f4765ae0a6a4d1e96f476ffc79f4e83aa4d7b548cf0c91f4177366c8b2ed94b690773e5a888838b281d5ea2ca8ed3c1a735a0eebcb78e7944b8d24b1f1b130e4d5adc293d83ba0a491cdae836cb19dd4d8f4c7ae970a6ad45229b2334aa29794880afdc66dec2b97538816a255764ddace47c2e8dd419261d6ce5d3b667f9bfb1b167a80ad7074b6c6a7cd4389c1a6637cab4fb3b9e391fe6f4cfb02fa7a20db184b15da4b69f4e329e52142a557bfe883bb783ed3920c7579e4e69103fb412ec60a636566e9926a136da0833f934e319a59c639203d8333fc88a1e567efdceff33fd260464f4fe4bbecb1cd79e734ec0988c02aacaa2e04a7e24462c6c70ce7077aa4467380d1d912a8600872d86567195ff7d96c539fff2dc92ed58fad0c3f36e94c1a6345c63378307b15435870d9219589a9329ecfdd38eb980bb97574f4bb0ec8b2afa36a2decb892f38c63081ad28bee8c85d507a7997ceb9783a68646fa607f7088602fd6f25de945966a2256669d702d2e5cadf540e992ea45bbd5c389598735b5ce4ee17ad9e71ca16742e704f2e061a01aeac38aeb5ebc86b8dbab5541bd5aafa4576f1fc6ade455bd6552cfe9c0732c96b48b4e4a8558b84181b6dae19e059e4470e3a6d052c6e53225b68a7003f779300b6c91b5544d222cbe86e920f9b20fe7a15b44639f32ca1501b4e700f09cfb7f8615fe23e7fa477de7df8a0900dd2f07c4034fc475a1e532d22d9f595dea4b34915e1a9808fc077d2cf735ab51d303bc1d8e858bce988eeee29f6930030296c4c1f9c918f2f5300e5f9366f9eaeba42f21b37d297fe35740694eae888779b09444f8fa1f8f49e4834fe270cc470e5ecf08efe8cde06bfbc330d182076e48cd798e2d734469e89d6942b7659e252b66045944b33b51521d418c60474b13649f3a6ad45fa697f3f7b026917d64caf124cbe11beb094a16a092c47aa6209dabe270a55a80f46139b478ba1ce23682b80358f53b8b16b65a468fbf4756bdc3171d4ad0b0a71bd5a6daae491361d09a297dfac59fa7fa5f42218d7c255b1d9a2bc6f16b371f0cbeeb8ee345e689e3c5cfa50a6fb96fbcafc188ebca97f9dc5a4ba60d8438fc09bbc78df4ed826ccb1da7c2d901a5287ef0cea975512b6e950da48471a6e6865fac6cf1632ae7c821fa248f78a0a42ffff195ab5460e28243000fc6b446ee2817de3fd2c786b8ac899fdf799fb1bf6aef69e5a76a0a4438550a2ab3d09182c1b1e46b5d9e48f93102539efbee779a0db4264d9e25d22cf7b921e2506ad2e4d43d3fd655c8d2df51e3148e48abdd66a5a18d1a67d8af5b430cddae8e90e4f54ea286beb07d3acc7cc26cd8c8f51b48ca38152417cd3d7a3cce08a195a290ce08b26c39a1bd589c6c35284188b6b4cda30ef87d8b50bab8302693ba112db988b1460562a1f61935716b314da13125e9b2935b401664c42c64304edd9dba16bec75dcad81e3425e8d8e7aa49b4c403ae97f6a2879b959faaff5060a2a30cb80114b5138f2f8ef504e0f240c05711d9afa00796d5f2a3202a7723e2caeb936ef17919950084f6690a96d703300195d6ac95afe5f69c601dc9672c1de381a5cc34b0723f403eec2a3cb60bae438d9b398a6c0a477e1f6e864fb8667e81d42ca5699292ce4cb02066f56c5c13933222b078f4ef460482ce212ce9621921ddb02c177c58937a215c034a3f3dd5c1651af021048027d97bfbe06da0cb15a8d18bf8e3e12bb1c13bbf10c9c9cac61ce30481c864ae4b25866c655793345fa153cf7c1bee5b4c774d7dc1f1d2407821ecfa22d9adbd189b403a7310d34757c8a881d887927927b77495f72fc4853e4d6e9fa5c18de34ad5955b206c100b1acee6cb378d5c92684164c9f3fade11a28311eabe88d91d9221a61c63ca5b321643777c9765649713c1335d684e9c6cd4921e6e99f5e809d8d147ea4e7067dbc5a5254b234f0d5de6694664d10ad753676385053a4d889f0f289fef9e34a34cf30d62e741d1f181e0b5f72a09384fab84e1fdaa44759954892de55389c0dc4b25f3604093c0db0d975ddb7a97b9e79920dbecf8cdee670c1d2f7bb37fcffa958321783b22af32c1834f212fe191cc14be30e60bf7ea04a4bf02b0e0baf6afc1e3f84d3194dae1c0ac1a21b519d74dc3718b7631ed07b295e3c72e8d1985e88de3efd5d9c1bcac3a5384948f69466419c397a38ea822a1c0d61b01b67ada27767488d7c369cfb1f79adc4dd62deb9d178b837303353c4d7d4badd1cb66877133d67f18154e3436911aa80c9d04b2d98efe0eed91bef46a05b60f74dc3b84fecaeb8690709579fd19f97fe401a336ac796cab5bcf18629be7032ffed139ec612a694dcc310d665a776f47fd7af1c90894219c05695dc80b2cad054141db9efa00349d4c0ed57ee0bb8eb26b91468b5caa4926324ec651665ca6302868a86913e5bf9d7d4dd3712cae836b51ba36a8be4d2c6a461bd957d1c1eb2f68f924144291b4c4ae62cf504b4987f46494b768d496aef0e9e36cbf6c2ad1dcf62dd3031839ae396caf4209ac4e51404840298ea615c5f6ac5ce1862d96f50f6436842a622a8f0ae51413670babb4237113a42d76f4239e1fed762e690e6f8be17b265c788a3b85ecf8f19a5fdd5f7eb0601feec2a69d317a8fb7cd7234c8860617b41b9e9ca3b8b5744387ef5c598402334549a2d9d62ad303b0be504c0fbd22c4113d2ad59683acdb8e3669640c4107fa11752e72c873a3e201554d81b06688121d2cd7238aec5b062a16b151190dc1d6be10d8cc3223fc839574d0e2cb6968a333870d499ef1bc4948847288fcdf88801d33ccfda6ee4c769ef6cea100c69466ed21180b8b26178a5f0f551a33b45637f8ec2f8f2b4d2b192459fa2a07165dc5f7291306c3a363ea85749c13221d01bba473d04e3abc1e4a07b0e30e78382e51340e12028f92bdc84c6ee4068d9b3d9465f4817ff087906b81f8ee80ffc7653588fa4e8a1123cdef8f82f2899fc87f542110961d867f40f42387c8860a505298e30a7ea40c61e088ec5198f00d1965df4b31b8bb992efc81cd1057d5a44dd721524017f943e220470c670868ee7f70f276d57ce8d4abdd1f4c8f9bd38a98b3c2b034a6b78090b7e3e19afa6f139ddb8896b8638322b66be48fa26af2ced3211bbedd37dc47336bd10ade9767f16eb6184cc60f7daf11ebac92203b2f09656890e7600ff4cd7d6c25cbbdf6887cdf22342e86300f128444dc1fdc3c1e76eae128b0778b585aba21875159b984f38470cfa40d8b4564302d54c798ee6c70192bcfef5c8c5738506b2525c3a278176031219292872ca762e0aeacaa038ea3eddbb3b32498956d3cfb7b7a3256f364a975581cf1b6bdc0a2d0bb159711b7844432780445027c46512ec5464876dfe3817e2a34227c751a782e6b1c1f7531f1be8d7101354359f70283092af67792013c953748079f20f9e90f885750e5a632f4e414e93251a5cf23409585d072ab61c1c6bdaa320ff2aa972fe18582559979a7c8c3f78d16f9ffa79c48253f0537d11036ff42e52b2138cf4f1cf9f598878fbfd6f7fac9dcf377a33daed2dc3069f3e9008299f7e0dbb9a5ef2ad59cef5db7d22fc219aadddb0b51d5c3e3de88277d14fa0facbdd14655574ef49fed6abe293d0841bdd194210a81f4610a3815ecbad5fb986120538a4749fa7f2c93d2d922b0d6b13bd29698c9ecdfc331e2839d1772acda1b03e059458d3733480a6c5e3fd4e4cfcd11be3dc277eb15261f83dd085acd6b847099de535b6e411b27c04fb92be4980ca73a03f7b7f88b94714f848ff6075e7006ff44a0bd2743ce43b89b7156bd1229c0b7f01c9b670c9d919717b769eb423c7ab53646d17c57f256a2576c8a14057b75da9f46e0cd7b6edeb9b6694e3d712ceef2950768768e5624ba5ee991f004fab3bacc08c3064dd8914dc3aa4c2c2728097577df120957214a0e0699a978855e016f1d0b58108d59a5703387f25fa1388a03228d284ab1baab24fd0c8afb6770621c0473ba581615dddf80ba6adf94937bcee67647b3d1c446218d34a1b06625ded816f3403f5c2bd7630b4644c48e11b0af3f39d03b128b34daa431adbc8dc317fd57817501f63fa4210d1870c98a93a1efc046719691be975c6c8991769b006d43291e5dbd6d0dba1b6c527ef60e684729288c4e58f8462e5dc86dd25d43eac162313dea027f0698012c244c7bd2bfe044f0703f085ee880ab3cb29ab5b4f1444d284ee23e837a3ae5d6cc03738ca2b02495c368ae1702fef6834b0c5939ff705b84c96197b712dedc88769a192d4dd84a407c4e451124a9116665cad816a77289e1a3d2c1dd2d3248f440a960ad47595a88e0607b23c5b96eeb3a0d497e5d9cc1c423f54ca2f9125504077dab52efbc1533066933016c35a32075ff169170a5d7596fea0715d6fa330aa90a248933d49d9e71f851dcd01f7cca6222832b2608464aae44cac1aee678fa9eaec8d5b66a017e195ff22ba3df56f63b6d28f889acccc011d4f112cc181d5520834332966c5a87066f72443bbcbb67e1b6a047deeaee47c23a011f7457ddf98ba4d06bbdc92e02862133fd592f4264453497036c8e0490f48269f39653bd2e9209ae4888b3d955e5deadb301945762c7a49600256aab0abb71eacff5155cc1a7796a9439846d791cdab768adb20700b20099fad05f386418b1c9fda04dc73218ae47247f87863776a0432bde8313fdb8e46c06741f1bda38a86c6a753b5a91232fd2a86a3ce360d82f178994699da36b4d29b7d31b7738c4956489c547600794d0ae4401146fcda191e4d09e564e147a66349149de296e5bb6f29224df814e164e49941e81e903d26bfadb1db11db967d5a3974bc54fc00b7e36dca4f513b3a30ec982578d9e99dcdb7ff87e807c091495281fb14de1f05549fcc83366581ff315379db4911e9ebdc9687aab6a75387160faad2296dc8077b3e3b0a8967222b6bb7825cd222128ebe3ace5c18d41c1516339a859406c749cdb124c651871320655b76a764c00a354b54b30f6211afb2e436a581c982059d235afe0c115b895cbb73938bc1e801dd9201a3d3969e910c6a6b962130784620b832ea283187da770ebd6d31483b89c683a644c30b4454005b1de488522c4fb81e48f9f827f192e3d0d5501e68784dbd7641f09c754b72b1e3bfef3a0595a57fb10d511b11d03551b0af5e6c632106c8392c24aa2e1e118ef9aa7dcf3c76d9014cf316b1fb7f3e8b83a76e07c4d9ca728e083fec0c6803cb413f28db563fb48d7dea4ec22c7a89f6ed720064a323bdd96161058c3ce425c08f1c6c4f274a5f6b20542498e737e52d33c59bd2eba8b9903e2b23d830fb79b5e8fe62a76db41c6cf7703165253fcfea02ef87238b12baa64b054a9a814eae2606138f7769190d716fcec825f7d6efd5471d3f70f2c0efa8dad8f16a249222f0b145b35a05755de3c58d6b77f8571a86c7b3ba066c3f4973a5020e194297de37159920ae9114c52c33d9f556fb1ae4961851059757fcc7c88777d69dbe16efc7118ba1185e09e81b0d1c9b15611c960ad4543d2cff0fdf1c8fa92ace9311a652b479f643e75849a64ea1d891a7194e7cb940fa83de37dc4441d26c534b8a296a156dfb0cbcb143a5651f804239a50a9ea159585a9a4821c5356036a1c7cfc5532dc560679cb2a8f4b8e457ca067a272306be143eeb960ddabde623ddcbb0b7af6986fbfef7d6e74342a9c0999ef1a00be124643a4841ba34911a21f897cb090b9f705af620b5d1444c8dc0a16d64286e5c6513373f60404b0f03be18a2544c7d7baab2ed3ffa5956e28f029864c55fedbaa58a0f9950f13a7bb9e1ddcddd26077427d38d19a6aa9125d562b582ad4dfe48e3b9f6592f8ad1d2cacc5587a2203d107998dbbe9dc3ca7f72845c38b0d173c964f805159496f227e5eaa21e47c57a346a9bbbb094db09fccc9dc5b8eb4f83b861a6f2f1390e338ffb77f9564720a26972d1c93b0e19343a543218a8c2f0b2c90000d66d387858c5a90d64a8419a3e6659adc6493103afc57fdb34ff0d7621efb5edc4d6771cdd4da838eb741c1c637ec76e420790435250886464eb0492413d408fd2128dcc0c74d40a7e5f9037e4a85a018f638f781d8c4b2eb94e6f5f028c161f736308f067276d34d16d4028740bd51e1fb7a013d8910238d574c18d94569316c96de62511f772aeaa42af0ad29cb5a753fac60e9060940ed01e1aedf4b17f4b08a2e1d4b5e02a0512805e4b2cd3202aac3117db7ab8c9df0bce7f886e2e005b0d27cbff804e9e023486ffe6f7005f2e44050a5e3aad300bf51ab71c54fe0b03fc13b32d92c44596a1cf66241ed385f40557341d521a16ab7a12a3ea2aa3c22b17323a15df6135ad9ff1b2bfad2b6b97146f0dc500137ca3f365365e99d60cd88ae2d8877d9edbb97121744747f216ad7e219b64bff399942c7d564ea3dc7408040ade73a186fda8153ab69aa095695bd17dfbae570195d358a3f9501bdb7152e83322d34bc5ae318840d7f268a50c1405e29d2776cc629ec79049a17d368a9dabd83f16d124a9d100c6d8a613e4e43f8ed1c6b7cfb0ee48e77c9d80bb502e99e891a6e371cf222ddfdc376780db04c2633d89c67320914654ed61e6e4e4a87208830f8fe2dd47aaaf0fe8e50b6c62045aca196e19b2ede38bdcbb87cdce01b5f8f44e474f934aabf2256bef1779b3999a0671ed01310f24a41b9d9a1670d1b094af9e2235e76cc0685d64bffd5e7cb5976e7e511dd24a7496a844707319a0783827106d6ae96182eda491fb61c02515da5316b55127d589fd682b3e8ada15a0bf20d37b4aded8f08de003d801fe79b256c65326c77112bf70458f5ccb84a338dd5fab79fd54047e26ab37167cc996a182112aba7c79c2c900ceb6ba4a19a996902b11c118b3224b3cdc6e35bd6ce53ea0f079265004664b3165cc4ac914159d6b4574fd6b838226bf0431d6b729003902e2026b3ff685e07fcc680606823838097ed5591ea051e3b1e86ab0474aa8739a20285bb4e8374224e8a2fa6a526af5c787361b5c3d9f60d62e740a9c33c70f493451db9b7487fdb450dc7bee8f11546c1096334005371c160114a4697801f195386495c343c1ed493c387129ad955db59e0db10da5dc761734d8f1ff4782b79d7adc33250ef6ec5605124c44eee3b1c99cb9dbe2fc6b46c6219bdd077c73010231c37c630d2040d2a261cd719a50f7612e6a96955da251a995f151934867c24fecef07db2faebed84f003a0a1490f307f0d00ebb9f8d5d1ec46eda8017400360c51ac322c32c5ee460f1d7d9f9e93ded76dbeccb4b8f4c846f1e86b5097236d2a5961e1864024054e1491a065a96556ccdffaa8cb0a6c103d32f9994978383ea21610f2f0ebe28c7eef60dbe985486482f6305d7ca246113f9be7f04b9a10e5c56b425469070c9d40bd4f0f06c50e4c09ee1da56d9289ea559c840611a1ae647cc4bb64a18699b99d7af136a5b89089c8904c72bd2476a4d60a4290e63f1d4d685f2aabc2c475cbd54cb58f826c93768918b59016013a139f74b1239f05e94298dde4f7033069dc5061d337e5d174a428324d083ada861dd26a9749da6195a622450f98312ba81bb9d4636aca1720b1de211b8e484145176bf85d1233d81eb83b5441a700cfe2972b8f9c04b51ceae4b67073b4f076dc733e04f7a5e8385cdc25d36986dc94d591d2dc4e245e294c4c99f13adddfc598168ab10b5b8cc374318483c518b66737fc4a1036142712270ffea217962617807af7fb850789938f2165a7b79c89c42cf7fedd0129e8fa6eb1c0a7b4494e04cdbf349accddd5410395ece075947cdf4031dda2ff5198f380ad7f71eabc7c64a415b4b5e7f5ed0a0bcc3789692db63de8f4f10522580d5cc57f5fc3b1d9ef092e272219a01beec0e42e0192084b3362b8cd0d740f50c9a243643b1d6ed7ea201dae93fb96b0ea19601b946d249a5438075f52659fa96015547c940a6aae4ae86449637574ec7f0717dd4abb4254f0fa199c0cb74d9d4bf852bfc4b7126e83867a8927c3846c418ec3c08d752892918b4ea32de0446f0ba21739c61cb1880f9dbb6801123fa7fbb87951d76207a52c9c6aa78bf20ca07c3d872b9183ea2ea4e17628348917d750c32307bf5c912f5b5d762630914563d0500e580834223fc142000cf9f9140246c8afaa1060417ec40a0105e427bc1018d7a36c084ee509a4037e5b4a14e5ce89c401af6e259aa48d47c298d7f7021bc4cec1520fd6b0cbf03c2af6624528e5c7822dcde799b0f528265ed6833d4a83c2331ad5753a52d7d507e70fc330fc8a5c949f926dc8144a0ac151d99f8bebfe2d988eb91ea41048ef479f6e539d4bb911bb4c1591fa240dbb6449d0d39ae6b6f1ac6f7f27d0b8cdcf973fe53e8d121253b83d05791e799e1e8dc3eebe939b605825ead463dc03863949538479f19f330aed1eed878b14e6de89372da01e076e4301da8c04e8d1bba6ba689e21692a49f2c4731ed200d0581f501c012b5606a359b97c421954c6f45f149b13c9035e5d6a34091b1f0923afee1536899d03a51e67763d945182480cc83be45e8b21b25ea34e9978b22012f00a0b2933bcff0f5225d168ca86947b1151625f32f5efd9cd0e81db23154724ece3dc0817be46a56437113411156602e9169db6aa585d7cb421451777ccbece93b0ab0b37fc0c5d5fbae36d334bb7bc114088a92e506f9f54e93d241426ac35bfa8742e160a1754e95fd03b1faf20a3c6a4a430520057c43bec8fd34546c62426bed618839286a35845d6e3ac22e1235a45d86889ca5544ac2536a19c4651df898b0f0642ca5b65fa1210009a247f1211b708b011033b156fa4d92093fd67ed6d7871b9e489d7c3d3e9f9f8d4df132d9a8b05acc9f551c96ee9ef090fd9a6b92cbd0f5501f3d9a27b0eadeafc29d6af4e6107fff5f2c78ef658a3ceea5fb4ccb60268c5d0d093609097ab31b6ce44cd61eb844901abd8b0da7796693982bccf8cce4607a41d5211e432c286f4785e65793e06e80e02bdb0c9dd7748d714c4c995f0c8e05aa65255fba2f4fde6024417935a429eb57c04b7026f1a956b04a734a3e61544ff9fd66240405b364f1b11b996bdf7edb376fbfeb2f24f42262cebb7b1c5eb6cd44a8b88627ff3893074837ece2c0caa70418b054c92e1b9be39723cf519edf693bc7bd6d88b5af30409f40085c9c5fe9524dd29ac7282091b1be85c595c1389b16eea655039c6b1df3f035b60ee93d8cf7c306b27b1d719334fcfdd5f33f66d48b3a3e504cfdf15be5f4780e3e4d681687cbe544b3b4d101fe519d49ecf94ac34932971fd417a21143484e9c623888d33120990e837b2bf19c702457cb8c1e40b2bf21163797a40e362940ea41d47fc128b2d0078e985cb4002175860022d9040041a884011987f4bf3ffb7a296c012288aa0ae4c0f4661d5188ddbc16175da8ebbcc7eb5a7a27740b8a0169ea8a04b7e19100cf29546d9b835618d56097051107212288cd42119dd7649852635d31023f5e238c572a7c3571ef3e9bf44189aae2a10ca2b75049a18f52b9b71b80a6ab952c7b072b26a38cd9a356befcb48837a106523d424aaa85865c4469684668d3dccaaa0be791d2f8182517268a5e126c755c5ad2c7c699e780a0bae804f3a6794d297a80831e3b323aa921cfe74b5415be138546e78feb93be0701742535bcba2df84633937331a7ff808f48261c9f1a12b1dc9a042eb3dad1edcaec595e8aaa1e2b3af793f131c0688aa5765612172bb18711d40ce1925da34acc58b19e8f905ccd6dcf6b88325acf50ad6283b797cbc0b90e7c3170971224dd417de0ee7219d0a150b2b447bac7121637ab7be7e789d67b56394402bfd437fd17d1216d860260e0e3ce03a5f7ec817ccb62134dc024c665b8382ff3471281704fb3a898b7842330b6c5a8dd61c8bcda00c4c5c4198a7004eb1c965c1ac0064281f574cfb4ca6dfbee20efae80c6e0c93432fafc910b4b7c312a10ad433209d65463b5209ee3d6c5bf1faaae192673d14d254806db76db7451b56d4482deaf9227aa94dfe2d2f7f62acae316a89869e077c223464f55309fe376d853998d9a0257d93b4d428a90e9aac1c6054c4324c074a8a2e0647f7f567ad4a36dc6471781fc806b7e5644b13e240baa67627cb4fa20bc2f1f7a36b76d7d9b9fefa604285a3dbf568dc1d1d3212ec173a03d74eec6dca8d0d0bf5eef43af43b3114c2cc2fcdd1ce0fcafd15eed46b183d033ecf285f5b90ab8d515c3790e1ea1117fdc1170d4353d3eefb2f7781252a85be8e3af259380f9a8617279d2e50815c182a7aa27044e190b1f457e8a820d4928977c5f070bc0e28faf1d3184cf85c3d9a6c67514d8455ff37caebd75bd355b7e7c61d397614a6fd2b23ed782d2599ff9d99f7174e4dd42bca7c2331e0407fc64cda8c98b48eda32888e9f5e7408e83d0280c582efa6234d0e96391b0f7e506995ba11f6e9b8b678004c51ab58914bc4a503067249e74d81fea3771332bfc07152b4c628c89840fa6cd69b4e699dff1f35b8b9512bdaf8053ebbd4a1e8e1760c5c11a19c1591c51691377b2e3165b20bf77cf7a92c600b67580e77e8576b9b630cc16e3aca2e641929ecf1efb97ae589678a28549f9b6ed499d061bb06facfddd68f9bf552c1186f4d28b9992d9a47aeb7d71bc14c1ce4139f6c3069ac90f84f4ad6f4e119362a9dfa16822c39b02acf82c7150ed06329a46cec80603411d89e3811843f7bcdb8283a823490d14809370d2e6d9ef5bd335b0d3ccb14585c4bdd243c183f8316ea5e401b4f39bdae0f00aeb69e73a61e69855d9859acaf1d6471928c945088eab873cc80849a465f0b7712546b18a3bbc0975d9e8d5e6c04e36bd61f9567c644284404f787612241c4624902b13374016a2fff7577b809d615f771bcb493980aed6ab11caa1788e7a13b13788cb09e6b0541a9a3bf2c616eca9b7ea194e54aeb76a458e81d40b65341c372ffc393ddd608fcd858e9d27665aa0b0fa39fa6c5e4db465f605be8667d56f02437f38f0e7526e3068852ae00f4cc015a42ff6c15c9797b84806953d025a1a9689e6d453a5b5740e3795f049d3ded9ebd4b23b2289696be683c8760b86d02e035a4a8dc7e0c1a68b154050f2b49dfe04d2191c64856bf15f076ef7ed9db11bde4128c6c5c0210f0289cf5c30100ed6d8f201f7943af3cf5c0e7c34e687dceb7ff1c58dc62f3c7e24389fa61c6e97ce64e1978cd2bc336e45616d69beab14fc62bf1a67e3b1ff6458bcd38d4d054c65e974f6cdc091f8251dc05cbf9ba9e8f77c6d11c38cbbc600ef1c570d131cfd695f1a97b2a1c9e406f01198243485c279fafdb38c99193184fc102c850fd0b8d2ff611cc63cb51ac0d443dd8c33a1e56139b9149254e118e72982884d96ce4a08961663828ed89c221ffb64d299283ff0ac8847ac2b93dc6289aeb928a2dac7436d1987c724ca0695673df5aef88c831abce2030fc1f91e26692aee68dd51112cbfa03f39f2d37730ba9763bd3ba62d73aa123db4d29c24e5aa2e1bc3d334e39189e19e6ad0f0dcfeccd4e2cd20b58a583fd858f0b7e1a7100dcd9c5b5ffb3e80f694dd246890f25e979ae5cce5b0fd0fe76fb3e97376cd7ecc211c48457e06c2426478baef2642b70cf9b102620ce763f226176553c723a860042fc04ef90c9b41cc423d555a51464936210b6fbb10997a71eff8700bae95d72343c6f96838dccc8b744422ab0378ca9aca33619be2c60c7115323fca2f3a9f10c5511a99367fbc99d57d183093eb0b458b4080b8ab5f15407de3aa9df474363b4e2ce93df3e6984a4701b946af43c6178fccd190652908f2e5ea64bb7efe6d69d3802ea67f3b0f6a43e842654ea45f6153e3a4d2e348a69664b001da68a42ab6e76854a82c81d7eae73f2218cd4fd2858766e04b9930cf7a15adfb29367ff25664c5266564c9417bfad5668a327a188e0a0775e151098e39b18741bc955732863ea8b058a92a53be8695ff43531629c4741c23dc724420143a203a74f9c0d4c8ece648fcde4c69f28bc25ad07ce88a4b42cf6d19c568d070d26497626e417d855422688ce24c8904299e7a01d9fc37dd93cb7ec0492be8226a87ccab9bcb7063c69f6c6f0488196a960b5e8e2eb81e8440f1063ae3b039dc5b99e0197d99dab598ef91703e7c0a5af1f644dd9554390604a42d624e647673870b941707b7529ae2d7e18f4e425f3e86a6f985a6efc531811f16fa2cfc8723b45eb18831ca4e053d84856ae53acc7f820aecb953a57c4e4cc549bc40968fb526e4c468b09a1d73cebdf5140c7133ee792a9a9a5580e7d4950e74fe2310cb2abda7003847547266e335024c1a87354ada7e9826810b415d500a5ec72b838f04ea5f4bbc013600dec969668c6e524fb7a97283b258dc3f232b024973971dc70a771b8ccaf64a76c5005b7efbe8944793a58414c6e6533ce93cfac3be947f1826a2b055962e9355f136f0bbf3e7ccd335c325bcc77c28b00e4c03e0d4ff201bf4f28ef5a7199c55ad94e1757257caef2b3b4ecafc975a5afb8b483bb803856090b3b4da2f37d83f9fd738ddeb19d083af566a07dc1695791e26b25d5bf4cba8b9046f013e96674ecdddeab16d2fa1865e863a5a51e3f6ca79957f54856bd005e230b31b4bc639970d57a95c3a0a52cadb0ccabc74d77cfb0ca9fa3eea0baf03cd6c2b43134b1fb117843241c622a7110cc28255215ba7f453b6e7682092a8f09af01dec95b1f0827322ce8a8293e0ec401e1f73469513ea44f5f3e13d5ea9990f4b093252a2d45743d3d6ba3d379cb2079b1facb9b2f0a24a6385095aa0e62057b9bdc276173807816a668b29fb7e500430d1c84080f4d02bf02927fc227581dd8753707d63cbd4439e3afd7df5f179ba6ee54aafd7918482cdd5948c3b3eae2c170da03fd1802fd3f60d8bcaf08738e2f6815d61fe310d23855d8972f7569607e791fe2f5e06caac5a2ab9f1ed0fa01aa2962ec16d454243a59b94e2296631c2b514aee8f5ebbd90cb9d6f76a51a280484556e99697d847552cca964e482c85df3ae8042ed643068ae839a4981d349d422aa488d3d68e98e83147cf1d1d91185d4ee600376884cef4582f8fbac760ae28ea627920f6d3e13349544a47c01f7014d2eea693ff5209b717edac6111e81d8838934d14a5e0a2d7ef90dcfc170c4647068348372b95296e316c8ae0e1c7c35d3cef788b622ccb917bd0fda60057b9a59fb3af5b5ee50fc6d88d70152fbd34b7d20595fb242f38db3e426848d5fb726b4ab022dbba6c9d0663b4adbb5b50c28a687fb135254c91ba035c6101dc9ba3f2f92cd49c83ec3c9fb47d4474ce37c7804017ab31335cb3908e71da423991ca8fb190940e67b547985cd3cd51814ae5f5a53a0e287c9c4c9de9b8631ec68915071d48548a6edcc0233777633fc760f0ba41b05b2c74935c086373c81fe719f1f154da46fe1002d9f310d2b93893795c00dcb4e511a1cd53e8ca6f40127cbd2bd3bc958c80587947cb85b91255e1b3166f7e892050bef6b236727f6373c6fdd69032d0ea537da7ef8a912a8e45069683005ef31c6cf50826c85278ce0490d9e0442cf1e06781139d9f250a4806c252565a6e07a33ddf4b8511366b8d9ec27a824c629e4dc138ffa83fbfce28c22d2c96ab4502baab5c94ddcd917b9fb8049644aa07e5f8d1112740666e2ad96686ad803663adaa4a53472f04d1ecf027ae3acc402e1cda38205c35ed5ba9ad53acd0e648a94e19628533c3b1fb0155e3c03186bebb398e4edf78876ba27f3ed12adb34d645f3512443bc0a67cc245495a63dbf97bbc842b5ed1e7155f9ca960fb8d0fb9bddc92d6edc1c8a7369f7fad3f50a8e59b196872e4500663980babadf27429503f733c0d3da14e6fc0101b09e307620bdd70ba334c78034d83d90340fd7c8551715c6637cc05890514aecf30481f10506894ca565b6fa0ccdbf9146315f20390fec0606a082841992371a3fed610989ad579faabf20c25556a2a7457446324a8e7c939d7f60c59bc33f0838afdea70b9b14e840018a35484f90c6db62cd53a00a9693f99f2e13a6daf0362c34b6d4d194a256488f1509ffec429142838e43067a74fb004d67eaa4697a02b49699f43c576465de491ae8b8566e709ec3569e57682ca36e937bdedd09d5b43606b17320f8e3b3273c4b35d0245fc223ae1136a8c1515f7dcbfcde9b3dbd8a503279ad70100d545d704b71a14668cda22c96541afdd5ad3f3de5f73d077b9e24c59b2df82733a48df4839a07a44d5ea48af376ad53bb95f4bddb4d181dc0707c6b160dab821f45b120fb96512ee9c98008a66a40848a15b3a04dd77b01e20b51fadb4c00cec42f9c6642688f0f84481fc7f98172653aa56d2e64c6b0b00220fd3d42f2b0ef501001d9e6a69dcc6428d30fb9055a7a70ed16984f0699a585c557c378f3e7565e7e3b7d7205ad73f044d07140535f88a28295fd832d34fa6ab5da4f9588a9791d34924320c5da0b2ab9bf7dc3bade1f564612b764e9e53c0f40a6585469a1e7c8ce4abeb9b5b3c8661584371c5e092659129dd42328774b27c2d18503110f220a8737b852167bc09dfbd8dd40ad2d0c13fb5cd9f02857a4d16a08fb129f6912fe1a279ffd0c0a974389871ec08636034b24e127311d22596b02e55c70e6d6de78c91c920e536b82c2fa6c5311c4c0acf8173514c939481d63e42acee28dc5d58cc84f6d89076e4315b07850a46409f75262536a9121825ec225e11d3f8ec6c1e016257b56c177dbd6e44e0919b3dbe76ebc4c9747df147aa40c1a71ff66c6bc4b49782ef1c8dd7963bac07f134b6d1476a8a51e66840bb19bf006caa000e93fa9eaaff830998ee32a9f2ddd562663921eb7f04247a08c3ba625e2a2fb86893194e00331667c6fe8865f258cd49f3066c752e2a28127d8ffdfb28579b99c9b5d560113b56fc47534aaf5a04d2c15da22b349940e28caf98a49c20cbcc5ce92228d522728f86c0b074e1fa4ece748a7e717f1878539cb0fa0aceea0b3f925032f81d8914a44b50ec678fc58c647d6b772b37948e14e3cbbdc075c5ffc7b76c5ada5272761e9cb9049ea8b53fab20a10b903afcd49e6ccaf3b165a6c9e7866e42236fa13703b83c8f3d3c496f68e4c2751e6af46a597826973189151fd6d66d728be8f45a7f5188a62b13ddbd694e1e6bcb130388b18628877c2d349cbf77157ef02248ef9d17b42e46e7ffa2cc71dbdd7ba23a695e018150e9a234bcf67f11dea7f329a73a9c54749adcaf8e308d95c57227812e7295c5cfcb8900b31cba0d363100ad072485ce690a8b3119898bdecaa7b44a6c8d10792bbdc185421bb8edfd6cff95f8f0ab00a61aaaeeca11c3b351be11b14f88ce1233d5c6760378cde2aae078ef525bcfe7660546574ad7b488e76f01a79b42e5a7888e366731d2b1e6a165ba3d076b4d52477a52c3fe1652e89fc814089eda82ff315bab83c55214c705eb3f1a4516c30a9760a1416bcdad0bdb4bf36a53b32e2cad9d10a82611163bb1941d2819f03a715ec2e10991dadb9a2bec3e1e8d991abb14fa31d7765fed9110dc38db9a79c5846a457752bcd11b149b20e9ccee3492b3d7a275da4f4e8faf6be728e9b64b6435f1aac9994736d834ad5f364067cc4a2a166751a652ec6b9ed306bf33e5d8b119697ccac5d5c872d0f713377e0be586770af18b5aee3ba61a34ea02cb759e8692ea2c2c029220f00cdd6204501d670ab4aa702246a6d6251b2b33699aaf4909105f5182ea100031492b0f9246622d72cb407c2e736113cee66c6c262eedf73382e0fee03241114370432eaa90db1646827e76042dd433db318d02a9a2049d56e95d8a87293cc54a9b71aef6d4fbf9f267801a61fd5fbc8637ff488ad2b9ea90fb095cf6e9db541cb16df5e3d2bb9cc09bd13c4318b380512636430fc6a4492007c67fa055d134ca83ad5de69c1388fd1e078ce8afdf86f478f6f0cbc50066025aa25274ceccd0778465c00fe2727df6c3314b607704d94b1cd889ee1b3893a5485dcf0ebaf65dc6a66ceb08e8866743721f4166c662d0dd546925830ab04a653691559ee9256427c67d13df430d5b101a649a7593d86cabe90345de62167e2c02e2bed706d25b5201c8f38617cfc996287178f0560f570bc133bd809b0a6455b178d7f46374ed344c144eb6cff709a389a4db7a69fae483a8e1a63c78b74b225a50aad885149b2f9aa84b253e67c254b53f5613b57a2a44cb304d1f8e40b6742ae3943b72ca366ad3d4b273d3ac088faa9cf68b5c525b631ab24acaf29a5bd779468d18388bad1042a80c0847712c35b74ad9b3f7a1a51ef28c304a403ba1780ad5d0220b942975e63536f262d150f88321e7a858e130c26ed1617bf209733672a457469a3c187c2d1c1122aa20dd444ec7b69ec736394b5c74ca3cc8272aabf447d0c24926637f83fe6a52873a335bd62113aa41158d839dfbcf847bdfc3a10a97481969e6e644a20a4a02deca0129639375e0a42bca371d0ddcd923947c886da71fc3fb3c0d1e310bcc1baae71deb7b7fe59a87eba399957e9a5006d463c1388c0e422ce3acdde71af60192b1b3549e1894cd6b40891d302cd647364d55839e009e7187fe11d5531853891da1c5770cc39ba855b39d28edfc08fe1f01ccdf65bcab3331fbe8f6729d32f1a32d53598f4b4e62615a06330a5acf43e5e58e56f163d57f0e37b5b957245adbd26ea7ee4f36a2d7f3ccd1ecf7b47856d27f43b4fa5b83412577fb02f4249d8dcc2b99a9aa3a86abc850e16b45b8f2151719bf1981ce7c9706aa9980797c7c5bdb852c7bd83c2cfb53ed0c860285c4a93d44aa61c3285b1a61c07f8f93e9b588b233f5a209ec91bd354023b6a4769d730654cdcb173480a734dbe10c8028c2beb95c040d4fa76954e84873aee53dabbf45e9e66f58cd02b409746fa5d342b4109dd16d6c2b825fe979d86e9dc543a904e27e57244fc94619230c09270e2df6bee35687311615e2934a889f57477b63abc30f24a0accb118081dae7d525db163d049ac2d9181f20de1ae5a07efe5bb16423d18a066ff72ca8e21c22cecfe0e52f660203d3af9f58fe90bfdda003f01eda1148d752be13c6fb054131a5fdff1ec93bda24f4a905ccfb656ceed0bfc5fbea4cbfe184cf5468de5398c30d45810a8464cb474681d3a0ce65db8ead60ffde8062ce0767042f24160e5f7937003034b92fc2e0ce393024cd3e044014f9ccbaa0ee07242a82303ddaa38e260260793ec32a2c21ca2c6ac894df621e065b773206279a732792a12e6db172dade7440db880f8f5f73db785c86cd9b92dd434adfae29cb0efc099e36ac2b1e0992c890f0ac5abe6091bd8230d50a65eddb27e45907382d60f7080d2113420ca566d61d4af9396522047020c3ae16ed84540dd65e866069a845b0b9a98c31962372ad215be42103773096860c97b668ec964b6bd69373e96bbb3cb6504803177eb07fdc947bed9c2faabc2d5acfab9ccfe95ac72399850057b843ecda713215f35aca5072361b588ead28b4b1c2f1113d4a508e884d74fe151cd406b9974750cacf76b1180e071049b590e2096b1823b4c2a5fd1c79c9aad8ed9c0862ee035bbd86f8016d6d811f46d4fecedb0c201037ae8c612717b2b5f6458a127e005bd4664764d3d9de8122aed9608442bd07895b2c0ca0801dbb37adb1bd74ed6b71eb02581687b76354f7f7f775109c800674c4ce1d2b3f17997b7a2b284859998f279c946447910fecffcbbce342fac8ca62c58cb448b3611e758e94791f4928b43c05a9a1090e6db54f6fe69698aecefc7b3e0c162bde116a8c0061aa8c0062a500656a19676118a1ab9a8e6cd3ca6871fd1269dbf193a167580de5be82dbc23de1008f26b0e5877ed6a56d25474ecf5c0fc9fac3c01ce944aef64a584c0036ab24686564022d1a80358f30217b264776b22a30122061bcd8b0abf2346e7bf69c6c67a1d69084ca683adb2dd222843320cbe46b203c0742af3a2a9149000a1787a548f5af5fdba25b3f8e734026684c8267befbda5945ba62465600850082b08bfbde631fb557615c03e92eeb1dffcf61593741e49f7d1f8fbf7d6df60f7b38dc756c0f39b6f08cf77df1023bff98eaa43fd17db98a4eaf9e6c8532046be28f2857cb343d807763e1578ce4c20f3d8c76e029c0cb6d960ac8b00785f83dddffc07be60e3388b6d347febabc0b3a676c64e8d8271dd7b4ea60eb58709cebbc730f79ef7f3b369f006fb4852de7440f826f39fcd07da9824cdd76d33dcdbb00efbd8611867da4cce94fb67f6b7ebbe21b0dfb68d8646a3d13c866158e6359b46f318065d106e4a17c3347f3f66ce7bede51d36a50bb2e09541fade676392f296790ae290154c812bbb20ccf43d26f79c549d283a318d7d2b903904b339bacc8fd3969c3a37248e9e2d9cd8a249cb59d35671dda3ade2a3b5dc7ef7950c2e584fbecab39eba9e5c34df710c6e7fd45e6d8555f455cb5fb1e33babbacb535a7870af75dfef3f1aa508fafd9e8633440464bedf575125fb4eb53acc7d8669a6ef799fbc1c0704aba90a93b9c5311200f497bbb2678e7a9fffe8908663a61ef61ff1447e06a721cbf733441fe46f58875d2c26e2c628739fcbf66db566e8d3cf5b2e96c5fe5e65a6fec35b288f9d0aab63e894b2195c902b71a546d1d129b345fdad956edfe8095fae3c3fda98a4adc33bb8db83377734cdfbecc7e6b80c7aabdf5b3eddf5d2e68393e529d9cf2fc6742cdd27ef3d65efe5a27ed72bcc2057920172a5a87229e5f4304ffaf29b71b856885ec93ecfe5a2fecc890b5e5329f76dc29a66135c9e983581469032e68f7d363ccc9d52758d0836084312aaeca2957d6e127b5edd1596a71417f416123289db514a3b16fb5598992596c4ed7e73f78ea52b4c7da24291eb131d725953d47441a40e85fceb7faa0e39685453b1a6ea138d225f01a49f4202c05a85ec5fa11017b0bd77df76da501eaae591b2ff061a816800ca0182417734b6dc1f68c40329e242e4370fc6708804f017c1f80dd100fe1bc66c8831fcbda3d1e5feb06b07b7512888d428f3fd37e72ceedcd845e4374cb22b22df071a05b92076357dfcca8ea9c8fe1b463b16da4939e170678b12a92da421080bd7c43c430244e7feceb343ad2a4ca1b5c2a33f4d74c84ff63769bb97d886b772835a9ad431fc755cf073e2b0cb653b79caf689a84454db94a2412317e19846f1b7e1ad0e8bc488a892b8dd8322aa0c1a758f595bf7db29c5e5a6b8dce7e4222701a25fbeec2ff6074a57bbcf39310cc328a594d65a6bad9cf7a044dd07e34bf3a08cbc79ce830fe83c88a39479f0062bf7db90076f9c727f57e38332653ab8dc8337ba20369177d9de45e44629f786e58afca4484e24acecbf013fa7921816a3ecef619005ccc7450403ba6f0cca57ce3e66cc125991b23fa8fb5c48bfb2bd865db6e770142db261504b8bfc737a89a83cc5aef88bc4641fa874410c0a7d35830c7ea37eec726fec72918a2a2d1fc4ae184fbe8d958f5d8d82657f0ca447f6ffbe263a45eee085a9689468851d44011a657ff06bc1af8f94fd2b65ff98c061f6b7b241a346013740402dfe5be6b6fa3740da3b8981d80ee117766536c0aeecadec0ec4154f42a878e2bfca92ba90382c051d61ab535cc995e4e0ee6eebaaaea2d864a75275a914d6d1d3c9d394b8a0974a9a12b74f7d72b9526118552c9a1237e3c91c3b1a340b5bfce1665ad9577c8df19401a0e2cf59f214017cfc69f294938fef2d4fe9e1e3bbcb535e7c0cc047007c6cd116e8e3c3f014938f7f3d9ec2c3bbf8f879fa32aa849ed20facf68349f207c3d74512af704fb61f6b3fd67ef048de30ee83453e38a4e4d37cb4a8721fdcc99be53e98938251c5f01022aef4a0d1a04a2e927f324d79db2cde64cfb6692cada5b9b47b07806b8c8ba41a2ee82d8dfb604d2e9150a90ccccbf3b20c8a16f99784f7836fde382ff780359516a3ad5c34524b2ea2611d75a8eb341a8d1a2e783f383300acc1b848e47d00a4d10995496560eeabc57103c0ae62811de6ce518c27c37d7077ca21ef7f82ab4900b89632291817f907000098862e7294061355a8bf72858927f2d5e0711fccf580bde522c902dbcb7df066ca9d071dc6046fa3d66bdb2cce36dc07db5cc2e13eb866125cc27568c6700b0fd147c48d511661244fbfa46445f7809879086199290ec1720f38f302674e2ef2e78187ef81e3627548d37ac034c4f46587eba1affc2efbb19fcfe7b38970204c82ca9b071d26fb9b602d7491bf0bacf180b516d658995354a199edc1d558ce8a27f2ad7d10c882482c0909163b96126cf307cfbc8d702ef0f71fec9904bbb078130cc345f2412c1ec32dd8e3164f5b9e425faf96af3c9e1da218e3a72f4fd1582ef2778de5617949a60f6a2d1a9ffc7ddf2189718bc7b05c212169f124f8ff9397e4495ab860588b6f412f0b6c3dcd82058b151204027d381026c13149f9f316831a2b6bb99f971d0bc95b5cf25b0bfa69c1e25bb0f86e4cd20a8f126c73ec483e92ce9ffd19be026f263024825f303a98a5bd4219d4589955f6bf1a7d7518ec6490be40ed07a85191fd358dd5f19f6d73bb60df9d8b5d899f69f5c80d89a3b51e7a60835c704e5254915fc359831ac613262eb8b972bf6b73d96c89173772f971abd7b6450e84419941753822472ecc210c6ec8910b559c72ec82f8cecf292e38533635baa017e3c5a8b2c8873c37f294ff99bac36df19a8b8f31e57ee041eb81076feec0831e0e3cf81b7830a481afa4a86280efa7aba85280efa7a6a84280201ef4c1020f8684b8000632f011020ffa108107431278f027f0a087020fde0a788fb5a20a8ca8e2c3b7032ecba5716bdc075c20ee02340cd0ccd064cd8aa6013105053f5f516500df3f531326aafcf0321ef4e1000f86541efc0428e0e326e5411f3227047ee6783891f3730a6befdd42a00f797b9bbaa30f8c3c30eac08803a30d8c3470616c063ed05e0c7ce0f55ce0033d2fc407be0582f8401f2af08196021f7827f0811e097ce0e708404006100fa84183e573808c1a13cc39b908e522121c73078a0eb50b556e1730d945ca45d847871ab772e396cd2d70cd2d99f3e0a78573c2ac20382617b1e8609949306c5a6b2be8412d1e3452d2027bfe91350f7e5ab2e9c35ec945dde239d07340fe1f046af10f72f1ea50bb70b958838bd0852bf7f7406a14d0c51a5c848d12a487510f2df8fffb5dac21aa44efef839895fb31f64c8fbd92a7c33b02ab29c8a0af50f048150a206781492470e3cafd1f10e93b798f0c7e5a38238fe4e9f01f1ccc82914110a993418f44e27c5a58bc72832012b809272a831ec97d64f0d35284cca047cafedceca1f40d3ac3e41c93f6b791964dc7be8ad131fa310c8bb5564aa9b4d67a6a8d71892b7f86e35a39d9d23148599675f273b9314d2b3ce4cb166b2db6314d1ba9431d4fb21d955a5a9fc6ad85da3aa5b85ac7526786c96045d5938b2e27bfcae39a6147d828e0c60cb95d403af3ca50d128d9dbefdf9821aac46aaa261751ec424202ae4cb4a8fb332f6d1b39cd16635812973e27b196e3a5a90cba8b055653ee8f15bbf85b575ec33632c59be5b78de28912f4fddbbf6de422246c52b4e37026b1cd137b1353ec796b69517fdbe80817ccb846b93fe3cab8b2879b13f396b4daa86d5c878da021478e1c3972e4c89123478e1c3972e4c89123478e1c3972e4c85eb297ec257bc95eb297ec257bc991bd642fd94bf692bd642fd94b8eec257bc95eb297ec257bc991bd642fd94bf692bde4c85eb297ec257bc991bd642fd94b8eec257bc95e5ce55961bbe576ab5dafd04d7ef294c3b88a6228140a8542a164c8902143860c19d1eba623e209c9c0a6b70c193264c80811f17025afb0519d6a9856754cafa6c96432994c26140a8542a1501f128e450b6c05b532b9098542a150281408cf1549b2f77a3cffa1100c0923553246b264ab4d2693c96432b55ab2255b267b3d2f57abd5ea4dd6544dd48499a6c94d3c70265c8c607cd9feb0cf7a89442291484e72c2b559c55e4a0b5c618b26e0167970472f18643bb8e0d66a6daddc4a5cd0c399e7f69271e0a4724b796bd57ea3dcec6a49268286ccbf550eebaa877615c352150eb763e1bafa5bcdc8bc7158d219e984c3adacf740ab657f338c75ff416d82b4a85fc39b907344697a0671640e478dbb32472cbb4a8db39c239ac344c7e8cf60cea9637058e629b3c621658ea943f3758b98b986cc1baa435a17c48672bbc53c5f774ad1cd8f43ea508667889537dc6578cb1e76c964b2adc3d5ece18b330ed3ec6197ed333806f7d55a8f28913ac4a101c7846a14904383dc262638a746698243835038f26cdcc66d15d7d0f2fced729109afaba14d38cc6f4381de293b4ae679b5e7702ab6c4d5be724e1dea4dc7b209e3497fe6830b6e28536e70b3634b6d4f6c420ec953b80639255cc432d7ae248bb6526c6a9db72cc9d4c75cfe6ca22842daa852bf73959c14269283cd5b797eac2e7d86374e19bffe8cae547e8e036fb9b77a7e87423060b405dcda7bbd9341394b4a627b260d59030ba22547f41c3528cbacc171b4ab51b32cdc4eb7f1c2edff6447c3bb7635b268b37882c521c30216542a96548ae5740ac30c0b2c19165cae30ccb0e031f1e4a40b1b556eafadfac3961a255620417257576e3bca6d49b9ad8edcb54e1d6d7fb0303a64a79d3676b5be9494da8a6db87c8b5dbcef8716f5cf8e058600588dc27dad363c892b6bfcd0a19ea5edc1599a4684e8b74d71b7fa09201555ee675f5b9ee2f2940c353578e362d9b1749f3d1c57b40737180b642b992f13f62013cad89950f78138381cf20db772bf9609eb0b4786f1838c9e36bc95ad09bc952b2dc92ace3337c4929cd26991cc989dd895b16bc63fda1293986c6caa4807359e1259ad4989a727d6ed7191dbec5a2c669a1526211499f56bdd0360c8ec6ee2c5a81273ac36ab19c794d5896ddb7e9352caee6eee5e5b05a795300ca394521bd6927f4fe75a6b2d374726a1d097d82ae24f4f8e5772dadd6ce6ba2e7ed7b1cc0c07777e9fe16c15d7e3b4d2d5ccac95be98ad360a09c05a6b1fb3d5566b316f8c62a00cdb2388f6c18f0cbefba62585bbcb6bf148b9bdd2e4ba8cd7e2d1b1ccc91b6da7ae9f1c3f93c22d4306b79337920890b9dd6584fc2d3ce46fa70c7ba4f6461dcaf3f3b2185c70ab2a1dfdf3edad2b0ddc4eb9bd93a790c815fa658f63e5eb9c54b86f4bfdb5485598eb077aa6dcde08fb46d96be950cfcf1b75a8491da33f8bc205dd85a537f2563c69cfa6554d3dc301524619e5473bb333b3d9ccdacac0333a245b724482464141101d830b722f14b45aa082468961c8fd0a01185bca26244522c618a38c52dad8e208b66852a507aafb572ce73744fc91a7cf29b199eaeead3bfa98d24bbaa451e47bfb107c76fdace5ca072d951dfd18fb4b128a92d34606d7e7e831ecabb5d68d0caee6fb370d1e1979cd873c65b2509ed241b9a86d47e531590c6b69b8580d6e624eb8a283f294b61d54ee4e4745823dc9e358598149b09f8fc3f32cb0e2e76360c5cf158f7d18f83cc96704c97fbe33e274bbdce2c54e72c55671b38f9dc7143b2068f67e464f55a7a5f3c1de0a1c5dd4e0f5d8efb478413a47d8efb6cc8e2588961c393a241789ba46070631146a213a5e1551542fc6598ad14cc7fb3cecf279ef365eb8dedf26ba1a7747131d6a2f1479ffee6a5cefe34c42c8159220482627f414926faf56938b5ae5bd3c657e3ffd4077652ff494cf6f42d6e429d87bac09fb4cd87bd6a49a24920ffb3aa491e9a2bc2a72bfc4600706b97f0372a64e29db4c63e49b4d74a85f13a21fa2bfd19fa6feb4e8fc9cf59e924699f7fef601b1df7c20a679af8f61d807ba20c46163922e8e59a395ae7cad74c18e2a77f530d171bf61ecb758e3c61e4a4091b1e7ec18c13eb3c9ec39354ae6b1d77c603701ce63aff17cc86b3eb0f3f5f3983ecfa943adf9fa9aeeb1fb98a686bc4326b91f0d7987bcf9341dfdd849c0f35d4f8a2735c0eff88fc01aae583ec953dcde958744ca2f582f585125cbd276cd4e316c822f80645654f1fc82f5620c51657eff0b32c8173e1ac55fb06202b4075f7bf045906cc117acfcc2c70b565491f64f267bbaa82c9b9e1c869e5c454fb91f73b5acebbe3ce18f42a47e2c85b2a90be3517d4cc8e587f2656578479eb04b619b54302a952a46b552b1542d92a78c2ce9963ca63f8548317675599ed687405fd978227fe24c933e7c56b38cb45d05dc7ea0cc52e52981f1b8a24acc25309e8295c0a8727b8c0d95662b5106cdc8a9d778629dfa4b168a4d6470c17bca7d51f3dd3f242f8cf6d653362f8d5065f9469cb2114d1881e2de7a8ae6b90f3422b589c185f194eb725d982cd5c19cdf9cbbbf5dd4e4bcec82d8bc74e1fc456df9ba3ce5aeae2bf7c72c4b8b6dd672e6c189b2a8ee3e7b4282f79cc953baec258e2e9ad73abcc177e5af3c57b93f6ab0caca17dfd47777dc6b4fb9ff4d604caf956734aaba209ca42e6354a06e6d2e639f3d75a809d77b719be620f74517b93bc8994ed933e5676392e8d48cb6c9a1618b26524acb0282e639c59ddbe3e81cfd88c5e87324593146c7700b0fcec31ae32bce5bfeadcc49db3acb53baa7f499015b5072af63e062745ce349bf27d45fa34a14c38a18ed4bf0ce38dc8fab3a5ad4efb8579b983a5c50c414935b8456bc1d8165c6da65c4b05a33208e9c67a3b4fc6a490617dc481b2977cddf8a1df8cb5fb67ae53e8213b49a19fd47c883eee23ce821c550a368731c2eb88dfc55eb13761383371cbc61b968d3dab836212a7be6d32313b6d84dc8b759654e5c90036e9c110f8de6bb63b96f44c95f49dc975824a459835d443c552648876052a813a63dd6b1681b1d71469e22f21e724622e008691bd5284818463b1d4a6b07dc521c51a753adcdd88e25f34690661c3cccb2a8c5f65518b27f08676e2d2dda4632a8afb15d8dce9a8c943fe7f45e66bfc5286fdf9fc1afd80d85e11e1c56f6ef6c2317f98833821939a2637c2324d4053399208d92797f6fe4b5340a68c3fb6d643fa1e6fda7666a5ac752e29438a4ec9bcc17cb3c4558223eb27f88488b73c4139c9197f2aac994fd4dcef932a18b7c1bc5ccf7222667e472c16d34da5a3652a36450e4eec1111dd97f8434526a94ec47469e0933feca1b2c121ae16e1e1409b348900ef9d692d3fc278c2af25d6af01509458278f623a4ec0fca9c494f953923d2e66eae151edac5366b70cca62c1f43e24e77654d09dc757fbbf7e7a779ef6a64b2ac0f72461ee8ae1a613cf14f98fdc14c985d7ec26dfb9a093fa111a6bc79f3b3e1ae9cb96b1b81264764ff6de429f67db319e9623f83bdfb4c723c995a6671a5a4286da34c508bbe60c226e36fddfd0d21e347efd45f2402246515b6680282543246504482fd05acabc1a27e21372ec9f3f34ef1240857e41555321a36671e4a1621331579d1c0e4cf4f3e952db26491e7d7555d6590c82bf74f1651854506e5f92df2fc623c915e0aa402c229b7fbcb0d5be26299d5be21e837042673cb9741b8605de55554a9d6335c84f432e93fe8a135b3174faeb76a51a22e65c7e261af0711bc980e35f635bc1e2d4af1a4df63b52861ab0c93c1eb4989bde90de1829795fb3d55a3805eeeef94d772c2164daaaac6e408ce518c317e65a2938952929ae4a30e3bd4999c994fb2993003a4634829ff73c954af140c155d4cb74f2fb9d96b91a68c3599a66ca70d2581b4a89bc339026be905cc11879469794ae629ee6a51ff960237950371d38f0ceeb216768ab75ad4ef437e1b1f9b0d2b88cdca459d09d2a19197b024b057961bd69ee3e42d5eece5327f46835e0b133fa33761ee4ce89fc1f3bb4dd65c9de2ab16f587210c3e7cfcf80104c8ccb6bf87c7448937add2ce6833f439bccd535565890ac2294d4d0f961839e5fedbd216c1d3a12e91f23b4483fb5967a8435dbf902bf658ce9f7e01725b18e47eb000b9df5fbac0953125aeff0c9f5809a629cf4fd6b0d95730f8bc5513f73ee8ad464e3610496148aca6adf43fb39a33520cc32a758a5bfba1b93a463b76d9ac6a6a4b68586bb17ee0ac8d6a1345a754ea9e1dbb646fb1f6a34573a3a278e6996965581ac7ea84c8562ccb7d744a36c5059d15b16c710b0fd9da448137311da37f6217fb8e37aeb551d513102eb8518928e10717ccac32ad46014594907b15860c2be3639ab28b2821aac46fd93ab06a139d623fed474b0677c5cafd937a0c8e2b14d32c2bc7b1fce5add65a587dcd5f596b6d54fef537aa6e638a27f557aa5a870b6aad556e8de28cdb388a6dcdd874cd5b469114d6225390bf6149645d6b96f5675966bb6218b6c4ed9fe15809eaaabeedcfbabbbb6c8ea20c624ad775f7edbebbbbd330ac6298563da59ea49114c540a6742fbf5f4615ecfb3b3c5bd4718d759eae19d6d8b45cd70cebb7b7335db7a6b3c62a76e93eebfad45837296bccdb62963df78136ea6aa377b83267dd9a6e5ceb77631b16040dc3e6a679787e46a9b5f1998e8562d37d76bdb5a687522e415de521fce53b08f41886fd0c073de81b027b8a37264e52dc3b5fddada3642a793b52a9965e13dea963f9dffc75457ece09fac73a16d063a509870bfa19fe1f3b96ff3c1d235e131eca4379a70e752c2d7ea3944a6137afdcf375c10d908d6b4a713bbf55ae6ea860d9841dea57101b4f4787da248557aa358365de4058e6ad05867d16954da4f427720b1509ce2cdf238129c89e080bfcb43c4133c983367b483c9ecf9e50f63c08237b567ca5af47fe80481d6a81b11678e64d0ad5e9743c1c510bdcf9c32d3c5afc0c7ee5e31e1461814c30e8e42290cdfc875d00e918fd8f5dbc300c568d03c91c738b0d84712d70cc1cdb813e8e244f292efe915dfdba5a1784c8ca45240f6256490b2c73067eceb4074558b9ff13f286c4e137240e4947aa3865266907edb6ee36b96996dc2379245467322f4dd623a582604ca056214a154385cbdd344d5869a2523b503be69c26cc444b182a6543a576c0ecc804695167c212a7a4a35130cac4c6f2972a66c5a1fc47b7913ac55d405eae967744a9147900daa014ac3b3c528943cafd454c128bdbc1ede07634b783db913b7b70926a875b78603b302a6b959f49fb819d2c4f39f27003c361fb9e61dbe6eb823647d96d677b390a61decf0dc2f0947cecf7f9b343dd9f7c304cd9ddd914ae53e1af8e21c38d0eed61a3c000bc4690301a4c69050f92e527636c194f66c7937832e389f4d0a908b1c7647ff23d6c147f79d8ef5484edaf0e497fbdc296bb3a86fcec06378ebc545c85042023013e1f7477f70fa494befc28dfbb5bca96d2dda5bbc3086550acec20dbe7fc01068c045037f9174028442bd7b9251e0f666dc4a8fb17b668c2a37ecc2a8f88c98801391a8d3427c80ec4c5320cf3e7705ca9180353c618980b669e2416e89e7b0e741f07e2a6c7252286f6a32b6b4f84bcc3fc40d992fd7511f7d1459be34d172e1131cc7125460274347064ff19ce61b06f648f800132fd8d7219c55e461f3039bfceaf19e6e1d431779f5dc6d25ae737312d6cd15378d09719033306e682dcef18033263416e202c0ff9339ecc96a351965f11d87c197d981f3107483c8890918708651c2bf63722e41d9c071132722480ffc42de57b570347ee9718d83766043819fbad7296f3ce797875778b65eab782ce18fd8898a72ccb6c56b31ed00ccb66967996659d6532cb62a66532a5b9b3d0cc672d6959ea1014aec534637966cf364820f3ac2c2e821050e9b2548af1651231458ee412b94720e0008b7a4a16e36b2e3360aeac11b399363d256f6596756c743a5e0264c8d034148f9ca773b9173bee1c7211d6b9fc1374fcd075304018d8d78e85d236a130320dcc22f6f2bdff9b1dd2d121203e63bf4d0dfd64c93bce99a13fa3a79f685cd4b64c93a9da992536db37b21e5c6f979dc19e7eab46426b65a2b3727c4f4ae6d9b4ef0c6ee1a179f479cc8fbec21e63b1ff70201667d9e3ce7dc5dd7b18fb0cae6fb1965b1cceaac962f03acbe68abdf5d25a39f2e0162bc28ed6ac55854966c6727bccfc3ca6964a1e2a330d33bd47b8602dd592a74ccd79b85cd3344d249b667aa4d0452efbf270e4956c3eb656f68f1b2b886de5a2201d1a85ee73c7ac9d92bd3d76b864df29b1b27fcbbab27bafec2f3ba59126905c26171293eb8c3a3289abd1dc6f08f9dee635d885f39c283aa591202d72db924935b66746b9869dd2fd46c225b83a254fd98c744a9b6fc40b4742957f8ad5329db807b911a665325ad7514b2a994e54cb64b4aeab7647b65a46eb5e3ba1fc47a492c9da8e45f3d86b0dd231fc63d8a1ec085ee835480db90fb911d7d229b7cbd8ece714b773865b78683f325331fc3d8d0941eee8b6340a9879ff11c98d5027ff11a964ca6aa8695eeb583417e48ec8fee0dcc1913a947ddc4833332484dca8434b68c99ebdbf29e5feae17c9c352f6694dd94f99caef90dcebbefb401beecad30b3ba3d49d0f7646d95bb696d772f26aeefbc72bb3d5c82c76f73ba34e0bf69d123612764a994ce995c4bdb804fef27e9b587ef7bdabc1650df6e048c869dc0bb3dbf7c2a832bb3cb5c7b851f6d088529e9af7cadd6bd3bf868d623fd371df969dc089aa2b92568e3cdc681cf686746ae284b52c1c9570fde3ed5077eaca53320150ff5ad65422577cef0480bcad3ca3c16905002c71bdae660f2c6b5ac1b2926059dc2b5402133f267b5cd276754515ea614354998f61d313247b5c1e208de2ef7179d8e0698307c88a233c2f0f108fab67894a7abbcf4927e6d5edc4dce3d2c468b4a0d982a68726c653ba300c31c9ae6e9a93f6c4424c21a61093c7b83cc4646d88695aac521aa244886986ec08314515cf21a61025427c10c2448829c414920a81098122e41482921a4a7abbcf4927e6d5edc43cc4d4855d151d1dba205de82994526a3531b2abc7cc497b628ea294524ae9d4c4846862345ad06c41d383524a35319a184fa1d66a62589a98676962a6c52aa51a2d6862a6c6474c54f1ac89d16841b3054d0f4d8c2646d3d2b83440342b0d4b7abbcf4927e6d5edc45c13a3a13427b423683b341436dd76a1eceae19cb427e62ccca40b35abdc42c41593521776557474e882c42eecc22eecc22eecc269b14a69574517cecc115d18553c7761574547872e48177661a694316598c88c3224e9ed3e279d9857b713f32ea42c3a064a06ea839eac86925d1d3527ed896928a72fac951a4acb8cbc1322aebc606928cd09ed08da0e0da5a150a793cbe572b95c2e0d352d5629d59cd050538342434515cf1a4a73423b82b6434369284da5c5683db4940643a5b7fb9c74625edd4ecc359449c94407264898e83029616e29a594524a29a594524a29a594524a29a594524a29a5d453f5ad9594c569a9d90911579e442291589445c740c9407d44caa22ccaa22cca0ac3300cc390352d5629654515cc4e0a8445c740c9407d501665d1170d6910daa2ae300cc3300c5d7abbcf4927e6d5edc49cb25eb05e8ce105195ef878c1c2dca424bbd239b139e9c4fc494f52dd292e655116b5d6e3d2741adac25894a5a1263dd1d3494369a82e7497cbe572b95c5dd8859a98c652580a4b61292c95d2c46862424c1e97870d9e367880488fcb536618861e57e871851e57e871851e578829a404a6add71298a84261a20a4667498f129812281ac53e5702530285922894405102530253b22a6195f8285195c4586b5232d1810912263aa24a655252a95c26256952525d9392ea55aa172ccff2b458a5b41455303b4d9a30294515cf9c49c9440726484804ccef37d1d128d6a46452324199a44c9e3031999c342dcbbc60bd18c30b3258fcc28786335cebbf6079ca2491be49228566098c8b36eb7562d46dbf78bd085fb472bf706519fb26a5a545a8c44eb33645ec140d000080006315000020140e0b4563a1300b3235d8bd0114800c799e4674689c86a44992a328a38c32c60040000008c000cc0c06230074895a59be54479965a301b49166d8c6af1996f2a1a0e2486eae3d154d3c1bbf88b959b8a78a9e8ce4608b8898b78e52a4c2a3fe3d25e383ebca0486652574355f8b35456e74e88c5f99a89f326c26dc621fffec6a6c7f0649e7acf6cba9fc9b7d2a4f48379e2624f493533263a38f780820f205635692a6c84abf21e73b44b0982f01947ca927334560abfcc3e0a8d396b9c0947cfde0234231021a51f26fb6a0ff7d4d09c845e669581e897ade95a02ebed0dce92b310bd19f913e285f8bcd18b53e89de4ba193fd52b903100e8b1f788c565261c78608e9b74235209104904645854c7ea1a58052eab438897b67d5c3a704a3d9dfa3277ffc16373c4796b450bebdcc8eb0a75d5818ca8758707a4ff92583eafceb08e9533ef12a9fb73df477fdeefed08fdb853ff9606783f408c80ca4c7c6e63b346bbc3df80ac1073ef9c4b0874b13f4098d4891024ff2cd863bb0ad1a533a24d6bf62ef2e940b1034379f12074c74a3e4d3be9e58288d261470acac4fcfa19a12888e1e8f49060e719e6b09bd2e2419877dbb7b412119131a05560206a9c230fa15a4563599dc202cff01714a8654508cb60f918a08f03f1a7fd5a5821d292ec4ccbabcdc67219b4f645ac1609cbac009743eda6a51da8b9f6756d79f59b4f8b648744efb64525b946bb9ea428e4c5cb8b8b5a097f40a093982546209c50da711e4b2273cf7fd6221c571a86e96990e77ebe8927e82d9d3c6e19899be091c82c198759774bb48d6a7ab20b17321bf3d2a704e9ff1f0e34f5e6627bfe0c9fe3183ac1729245bd35f93cfb0ff99e173db9932f6e4b5e2382ffd9008b004b883703cdc17e45aa4f4141aef9def497a2c76453aa1ba06ea3f3db671d57314881339ddbe458bf125c612bfcbe152be33820245c2a601696cf136ab02790e13db39752a8e1b741d150005352ea00bb638a3fb8d4218b5f0ab42620681e26e14b2b4f63acd83a3bbbe88d2653657bc331e48a9bc54e48edd86fffe1ff423267a3ae0d28862696f6b5840e75859231997eb0b551eeee6c959f4530382ec91f949e522d0f0014a114e3d93750c800431da161106d55f4ba4b049eb85232e2ce954ba56bd5a64c3a51d4a9e0a5e2156bd0cf1c60946e2e048fcd10f1bdf965b4af68b89241d39c1b280ef9873760f1bfddbec56ce98b97a6d9504499f46975dc28bc1ba1daf0d12624f7f32d3d97a374f570712284465f3ac397389f10c0701bc04dd1425ce2ce8b10535db6ebc918f93a86ff0e442f046d160d08636b854e4ad86f1694e635f7582baa1e9df7a1f914f9ac28c1248c66288297174d46fe4b81712389ebf63657418f6a1d846c1d5bbf32a00621d7132201b0de256992dc0725f58ecaaa6f8debab6fe490d69ae76a64a10f9746925e70023e9a05ecc99909cdbf73e70b6704027231290f3b51c23111d5d36a1da06f8e99b106031416bb504e4750438d067d22c5c2f8db39ea7d2826e811f34123b703856a4d430ade6ba3343d0ee83205535c9581f1fd94fd70a322973534d10d9869116858863788f13e312c8a7a8953728de8ac83e95296391f430f5d2214f93480bee3f202435107863c4b8a695ace8bd684f2ab5923125a34ffaef01aaa67135d0ecf73e70769a4e7316383b22ac17f792a1b2bcd8d1f1246aa7638f7be810484f0b4653803685a7cc8c94dd27212191ca55cd1722dcb2c5732d4c97f154f58c9b2ffc33dabf2879b979cfee07de784b7b47ba032072f1592043e2e9835c8e23e1e2592cc3338f0a4b6e3706eaedcd60e0965e9e99dcdc5d2812043b3b21c37fe5f103977573c5c2a3ab36724dd8f4168ba2d033c81c738c6e4af7875c65e92537b7bd3db8a99baf7dca7114d52e5033c0e0edc0a4ec7e2b946ad6d9946a7096f62edd2c372c122c8e82e2cb1ecb87b6223682286f6cb95604845c7f3201aa4590a06b6cdf4e714356d70983f978bec169e6756bcb6d5b670666ffea118d840306a081ec037b5803955db5340d4b771a39a910cb8ff9f2673225e8d31fc0bc0955d6066adef8d1b2c17aa17ce6d8496fb6e86f8d4c3cd572c74c223c663181fc55e5fff22b5558695f0389102e2cc292afa2691b8442b1379c98fff28202e4b531240f02291af8975cb1191bed9df33fe8f9099ae5e1c0ca8129e0dcfe421fe26f1ab2ccf870389db95e328ec22fcbf169e9c4cdaee3c79148ea0ef31e9bb834918cfe15def4e14f883ba87d44d211231381a097618c25998382d028c2f2c477968106e498a101faaf0c577c0e655be559306c66363d4a79fe7499d559c63ea864abb21f90c9eb4da3baf5312c3ae12b0b6118921eff17b41edf66f0e764c164eed7a897c9237b2dbd0d0e5a8ddba3855c70cc854513b9bfeca92e4825e56bc355f04427ed7ba7488a6879fadcfb4ed89ef7f055ef74770c545cdaeb0ec695d1ba47a6d5b59159d3d7ad84d54bcf611520d8e53ff4a7afde36dfeb8aa62593b67e7da216fbae457df40d8b65e4b2050ebbf6f595f13f586c46b8235768e50e2d487e087f41f6a6ffc7521b733c6a4e0dcbdee3003d5a676e626c1524607d5091f5afc1f604f2bd4e8b0c1cda8428b308624a660315876a9cbf215690bcacb9771c9b5090af572d13061768454aa6a17969344a93150af3f78d4fc622858525fe8f10c44f255d1eed3a0b5517dbbc51f97308287b9d79fa16ec6ce0a13f3765cb7e105287d6761457ea0825c77de2be1f5fe9ce7cfe575d755d5b2866f7320f1f6d68916531c88f201cbd3f065529fc4b9179193d9d9a5cea9b812747ec31717a266bcf0af147dfcecd1f20718af66d55d0beb00cd32911a133f0ada815af73bf10cf60de7f613540d1b0523b6353116a499197ff3c960b3f21d989d00d622761c2b62647050762088919cf74a7d4f99b127dc08cf88b1121703377659972d7814f5b7ffa5db7886ee1e85c9e09f924532358d327307f061c98e8374ef8701a6fac2239230288e239b13207d0e91765914c667e6dcc660bd4fa95d05dec277354794704b1f747f5efabec1dfc8471988195f5f0829724a7b33dbd56c0e738c50e12e0ce802cd90b2f8a2aca584aae32cf9a0b1f8c6429e27f66fe01c79b2fec452419d9550a06c3a554dbca907348412174137ff2134e603ba4bba47a3a80439e7d56f8a96ea5d9c9633359c4bfc17cd165d6e02ad4d30caaad53a6272a315003a777619d7b2dd97d96589fce378385f17dfd0c4e917c949b525660caa32c86f4c41cab132826b90dbfc66c256a82a185258645832265ffbe12b59ff59a0c30c655ba4aca682eb33de51f71b749a9dbf8c8a579e6b19797d23aa9a0a16d2081afa105067d201ff53407a9f26a7ab56eef821095fc87468c275826358ff4d4f52440e946bbbcea090d5cad9b752b244a9485d68d7818c012a1615e299ff2be5d39c4b644c61dbb0192ce9b020953807debc8a2f78968be09ac322e9046f22250674deccba6959d618fb412bb4c0b319ad1464253ac903476aefa29324de4405f51fd7b87a18cee3118624359c5945da6a919594d9d8904a5d19cb2f53b8d33c2b2f24fda1c185c3090f508d5ca12b0f9b08d9ce03b3a1d257fc9b6bded57f1fe41ebdc214fb0a08baeec3031cce50b022405a10442c58174358a73f47e66920139728d773835af96368fa3e7d1ccb3307b42d8e97b5f6f229afab32734983ed96195c83e24a343b1e8277c7c3c79efbc138165144093d4989d5ce9439c7ffbe19a5fbb976e6fcd53fc7a1456e6ba53845f9a248e5b97144b788cf65625eda832c754e179c3ee3a2671b825e86e669b0a9f15d4e2f99a563546ed15e01733faab2dcb17fbc64d95f05ecccb797fa6a5888db4147ee8f9a8212b081145c90b90bff59668a2e850f6cfd2e92838c96bf34fca3d440f31e97dff200e1b4c92f468d641a9f1d61c63610d597558dd8142e6d2cc300ee82d96fb55ffe6e8e7c759a86435f05e0619daf63fd296bc90f8dd3f981836a0f50ec878616efc57093b955d85a159cce4cf54a5704a12ff53ef20db6d19ba379a38d4f812a6cbb42d198e46c8f3e2673cae9a42d22aa871ad1bcd773c8d326965f115819888e45602227718a6291d185c5062270cc900275c2633f4a90e8cdfe93f1e8cdc9aa561452e766a7c228d96c5b8eeb72cbecce139fdea765d55fa469d9836e35eb9689a4dcb58285582bfa258213639ad1218ec54f8502f9a5a9579f368a5418a85e230a72570c9407cc0037170c3ed13661a02bddcb2116386d97e5dab2d3fbaec0d831b7a79e943ec1f7b7017b0bee11e8344032feb347d34b44b20a0dbe146fcf6453f9c46e802fdab74dbee5a6d29f889806bce312a5a1e70dcfb187ca2b3545cbe9644c6f04f55a3ce59a8631fc218b350af751a892907258866fdb4a4e333cc84ef24a909b19ef5de821182b80aa319e4d74512b72dfa788474fde57e27ae7de2ad0f8a0a2da9ecc5c30c692deb6d8904f7753b6fe46f58fb2e85d7b651ab109d21439d00c05fd4222f131819b22f43eca186aa8aea9566ff054213583263edf15a3603c63b800620055acd6a139b877e2f22774b0ef76ad39b0c0d072132ad830343353a40974cb264c8fa33fca602036d685948204366b10cde819297cd34e210c3a783bae070b4012b4366b7edfd20b0a06148f03db2108557d67250bf29740e702474956c364346a673312da8ae9ae6d00bd6c5aa69ced573abbe7e6520f6db585c23c370c46786ec8b3d74c0593325c46214753ab64376a7ddfd0c240503d85a4313277b859e2da505ed52c4a6f32ff10265659d33f5271af0b4fc78652d27836ede9581470e074b4c0d5f19edb83e11aa3587f84e2f7cd3830a957c23f6d41ebf39bafbdc77c42c6d381a9cab6310a1597ae8ba664f9cc4195f1931c8e3cd4f94417d97cc8db52895d0f1186430629b1f579441fa979dac0689cceb126acaa04d026710f02f25d9193fca20d000ca67bd49e860c69a68edb3d14a94c1e45e7cdf833b309243f9d48c4200082a17881a65b06679065989c6da3aa53d5bef41accadf69e20721c2600140824d84df3f7f8ca5e22f061a7cc9d333b133871e801c9a29c964a5aabed0cc6202e50b0f69f906f334c30a7badc5a8317ea34a64005e15b564e9967ca30a5ddf46ad6f033516063b224486130a4a59179bd2ecd20daebab3f66d4a250300e177b63dc05bb8d9d19da05cf76b2db4c22075a9d082cfec70d136ecbd45a4c8250a00a51eeaf3463207b0e69d6b8584b831c1fc3cd8a8b396564379673a498f9b2418c0b04cca6fe78d72395032137da0cdfb1fe4df0e08aaee54930211c632394e0033f2e8f26d723f377c7b4829d554c34d7cce1e75d5b9f1dd25556f2562e2c6eea1052c1e351122d0a2631870326d1037c4647f9d5e4f3b4882999280979526322e3ee726566a3d0169ea2f989d3408ee879fa26408cc3154eee235156042ba50f0956ea5b943017bdb8ab2377545dd14692558b6579c4596a76548d7db9e0f1277775abb8561ee4d3710f0f82bfc8785307d7347b532ae009a5f48b19f32fd97c5d04608c2f11af4461f61927bf51fa711cee529e567aba7df95e7a4151544cdc887687c9e37a22e06162c7c32dd1fde8bdcee45d9d28abc56e796a11497313d4b0d1976f09631d6db7444f16d34dab58492e79497bed57059b7c9ec3702b31a8639c0712343208849b5ba43f20085e498a2ea7599480c54938cb4fa8fa4872f59a312a4020b6e676560d217026c574acba00dac5a94c1678c91b59a2080b4f78e1fd7bd70aad0e836a75a1e079bb5aec57e3c934cc774c1ad7207eab48c2bb0e5216419ad2e93982638ba086969e6d5c60be5fb345d96b5ee9384dc2c8cf96e50b9066abfda06a2fff101026b47f5264462e1a33ce4f2194cd41ca5ff14753ced40c9919486a05e9de3f8fb77687ab5ea09500fdc1073920981f7f1a52925077804ec7381807ecf0bfcede940f8bc5a6dee06e30fe9ad525e452ce10a274c43842ed5c6fa3d2c75b8a95afde981bcadffd7b7549b9c2f5ea952afee42f6e4afa602ac0d7cafe1e413081082101428f96a8672d4793e6c4d6b850cecafaca6b1e1d9feaefbe267eb97d08481f30d6bc4a30a569acc1ff6a6e2a449fb171a95879b24152878da4197409b80e14ebab06111068c60de27b25a371147181e77e33071b45bf9de5db60a6b6656f0808ae9a414899ee5eb0c068ce8f76e405d2ea32b24e8d764d9a1f796ab90489924852e6050c98c148f58bd0b080c43a82d0bd6bb0540096d347a2abad3338a4c1d30e3c9df16b2b908ae068be0d0fa3dbf7b41120818c975a542c8439f6b2c62204e98063310307ed40a602e5439611120a5d36e610ac3aa260322812edf59e3f28011b0406d3d8f1fea1e39a8401537a9ad1f074fad6bd02a9c64a6d1bf75b18c83c92633a93ada84b29c801199e752bdef2bf2dca3158f0e25efbc47e0548432fd0b09157f9f284fedcb3329645f6d56372a5d55500e8c7e22eef641012b57ab9d4603e2232be0f25975d69ca5fd14f53c2f60c9ba9684a00786861a92dfa179604acf005ae8d8ec4d5648dc87afa66801c0a3f461d7078da0a75209fbd2aad0e15260b90832a219edbe8777319048dd423023f281b9ef635d46c2eec0120cbe67739d879c7b54693de379b50a43098e75008865b2b4638d0bdbbccbda89c616ec114bf8ea47ec5503f4896a839ca09a8f4302a880d0d43fddaf38503f0d557639c8ee698c3034088fc62dc0a59f6c4307b5d6ffd9575f5bfccd2491fe6c42b89ae5dba8b2f8d5846cdf5eaf72a16c10cb0949a7869237a8c6536142019500e5c2aaee2c666d0796eab7b5347889229ac38346d3bcb5ae300970c35ab5cebd455614baeba60eab22158f16eeb12f12f4339d62b5eef6f76e70ad242767d3f82f1ddb81f710974d432968e59fd671cba41cf7b1bd254a6c56ca2a335c49f388e2db69f43b0927cf299f5aebc6e3cc56b1b90b82d6f139a8e32610fb231192a269337baea4870a6b111b8ccc03f33a5483d629d689805c53e580418890cee7872980a91a6048b42569278e8e6b1dc30465ff293e2879c96105badc4830fd3d68ea5f5b9b402e33cd1491cb65191419642e4eaf0f46cbd13a9499eb28e0faf4acdb4e5e557ede53d6ad73ed1cba9986b034251d5f7a6010a17ebc3df8506e78060f121c26736218eb8382564e8b288c02c047336445dda0b8590cfb13ed7b4c0015cc61128276982c3082fb9c9e394cd3338006fe25d0240d8afbe5a6291902f10c2b61d7824eee59194a4ee93d87255c57049488991d62a4a2d5e4aa30bb41e45c573603b4d711cc608889fd36f988076c2019de18925d200489f1f45bee3bc241fa06a0714335b7eb46fa5d7db635165d1bd0bc62fdfb1253fab1d24780770c6435149861869524ae177d137743b536a425a3226de977a3345be03d414e47440ef1b57fb96b95fe5ae02fa541f8bf73032a12b72a77f76fccadfa947246f1f95aaa50114d6886a48b1510c03d85dfcaa280cf8e4ee09be4cbfb367052cd959f3a8b0279c5c1cc499e3320deb0463c3ecd86c9ea3dec2258ad9fd9fd40356c11c55b9f341df6412d47b7b3ab3369b1016167172eece5b4d1ece50afe4525de6a076d67b24b183de1618e22488407fad2179e17c5477dd0271fb60fbd720044f5ffec72c9a414f731bd354a6c36cb9619dedb424479ed347bfc8af6334aa438bbe1a86ef3d9ae438b78bf3dfa712b0363488d88774bed038aefe3cba928b44f365a9f6464767d8495e12eab1d60087362e6dc0985dcdf4200c8ebce2a1fbde4f103e26d0383dc22cd11aebde15281556d4e9b7c0e9a75ae81fd3823998715d90df30eec5d994ad7d12e9365ccaec88cda2d7f0308ca62438065bcef1f50ac7f7ff089dcf274d3a221d41e0645bde1e5c431579e68f3c354c74606f3e68f83f210061d2e9d0c978392a9e7968ca4d38a81dfbd2483bc8b70cb95fcd5aab434b495d870596030428caeddfbe732ee8c3129e1adb9c156a3a18d36da09fc463826c2fa19211638530f7996e2edcd32d4b2e0ac997b58d8655a33a05c63c6dac8c7632c0df210c303489059dd467447d4e6da8bb24c2843746d50f72f740a14622a29a1efaac4cb9e064083c81584b332bf2e33661889b04f1ddff74ef5656ee08a4c3d2434657e71effe95dc55cfaecc307cba8fee845693cc1480d0062a26806801a0a8d7993f2cd5f1c38bdf1bb6b68f5f684ecdf2366f50b3e425ffbc455e1c3173c89d7e531b5429676a5200295112a05c18d5cec5ac77dc52fd564b19af7fa23d3ca868c89b02484c126e00560a70cf22be06ddba51c75229c543851f871789f8eb77b114c0c68345e3934ff8cca7e2b3ea99f9a932f51bd9fcf5fde490ab4386372edd7bca356694e22163422503104552d310d0ab132f632e92a630f6906bd37fb604f88ba0893a3606dec7c56f04b0409521bed0ae8b2c2c2f6107c8bdba86857c199d19f103560e39020252aa522a4989bd94eb8902482848d90f051444b9383669c4458f395420915d29c6df834ced6bb5114a64e6696872c92c83dc8bcce3697600b42c140067ae0518fd136525b58925016f815290772efd1b4662019a0af5a0ae3b7852d0885e7787516ef8e727f22d00a3c480dd8382569eb67e1a02404713564360ccbc612ab2fe7010707cf270f9b4a09a8f00e0339950de23e7a805c03101eaa79727dd6442f1beae14a50b89c273a73391a9426c0bc0ee55b981950031ab8ece51ef1c2bbc93e525b033500853e4a7478b6d2c4015d3d7dc5c0ad68cc4be2f8dc4d5d76ed3c63077fa23d556e65ef418056c5f57095a37719d1ba2b91ba64a7589c38dcb6a2ad8718ea97bb1b0d92cb09099569ed598ef712cc9a500c60b48c074df0074af48ffce497ccda1fc8eb4731450b68f6ba06c00fba7f9b323ab63e7255ab412e5fa7db601b649f825202b0722f4d466c6f39f47b4acbc649ac0dc17467bec2b650a8469c119af76fee3822f0d1efb1f7e032bbe063e1e0732f99956aed7e1ecf7af01bbca896890f2f7a0192842243dda17f409067c8b1b2bd4995d3d19b635d8a27bfc68703b2f8b049203511985c9458cdd928c875833666243a3ea3fb8f77e5c8fdd912388ba5aa8241de23d8be278eace9cf4d604edfcce97fb908627693598a8facb6bbe2de50513557fc38249708aa1557bf03d8e737ef3c535172afa030fe00007f559a69800fff3c91d24c3478921b123d631d81c33d9b3a19303d5059b59039e9c6a2042330d39f2c268b453fa7d8a281cc468d684a23459ebfe95c5e17f488b926d9d5f4323aaaae3b3eea7877096d51fc7a79e521b8c6ad59085d0db055ea42c1a784870c92b0881552986d521f754b3c9c0379ae83d170cef085253b719365e2139402c1dae702de90d3e11edb209c91f26e40f010cee37f05a387d144368b082d06856ac098f7919697690416a0d421ddefa2d4d69a2c2a0ab628cdcb561a3e57f03db56ec9e7b3b224a7d3a69cc1c4c3aef14cf51699e5fd793a2fde9f762db0ff05084ed204832ac28cc2656a29b57f8e26d78a7fec5bb81e76da07a1868f73ab0ab85f6838d9f374dadddabe8d58759ca5e89a7412f1c7c86ebfdcb58eecd1d503c3b0d80deb2fd32b69c1425082b24ed32db83759d88e9966597fd00e1a60a5278d38360ebb1c6a6130125440f6630e3e3bfb467c6b5fded880485c2d0150b41f9c3140dc642d1bc6ded4e943e80bb43eb41af2d9d62bd9bde4e2798bc3f41e32a4b655105e50688baab4c5e95a5ab243bfb35ad129168af9bb297c9259b9bc264251efab096bd68b1c2e78450d0826c446e76d0892894d3dac7fb505b5cbaf75c1ac9fa22cb18539200df78c1697e30c0940c493198dcacb58544174b2d52f904446f4720fd30905de7a4213d0116b627fb23f37f3e403525e112f7989d8ba6868f9659506cb49db18cbdafa860fd1cded0b3ca425796fed515757461af9604cc8deb0677385be0ce222cca72c99ea1372471df41fd275bb4897f7eda55936a83b929431d4fee345dcdc1152136150d0da84b06ee4803c701c1bc225acc6a6fed9e97a08a2935583b5e2fb63736f5be5e93d5006b78c42af5c3012d1d5858270f880b7770d54664aa61379d16cd14319b26e63c5fa94a72c0efd6ea70b673f4c701809f008072c7a1a3805888ea71ca14ac1a005b78e406d177aa3520bb0c808c656551db87b43ce305631e9f82351ef2cb8377590bf1838f88720de952341b6707837285d7186f7944479bf6270a5c3b565fb6768a63c0b81df22bbaf6c55211f6c6b2f727827bcff70af0b3e3a3d54545d635f755bce882596c7b672348e76f183fe9f1f338a6b9e85438ec49993e52a1e2c521a1e77f027241b15682614db81427482a714c8f2969a3d45802c86d20678b0951081492803a94081f464490725a3e37bcd8378f226bc85a53b3e0a49b1ce4330a6d9c565c9c8106b0c054b0b1d812e71185d8c4aa7e614ae04ec8d0e51fca94d9a70a276750a405692c568b2581a147a22e0a20c69f66738b692374533cb80bb4e6288d0b910642d6c0830ca47b93905c8586df77431044515d069e4026b48b427272e0503186ac65a4625556888e157c354d88fe41c2d3aa0cd3e4588c9e6a55655ad62d5f7205b3d9a988929a547fb7309aecdf32f873f0f11008273dabaae080fe15c181987cb1364992b2505c90979c42541d80b9c51e7067e83247c7b685e93091810ec25502ad1cbfb1878f4b9a857e92b45fd4969372d8cbcfff1c4926c61ded8587216c23183804d5c4905fe7a39b2e2155027d39fc26bc1577ff58d354d04338417f3dad78b4da9379ddd010a575eec8510188aa42b3af2928c0cb82b541078a8cd17471d1e258605827c16f655502b6ad640fa5c8a6c1c23d814f3c50832f2c91e846851ba131997060d6ba79d0999806302934226501645c9cab2cfa3d529af060d34fc82ad7085189b1b07b91897c3da57fcf9992e9f022ee1293429b920041ba8faad03dc332d8e3854f2a5347426289f9ef3ce1452918787a55d127211f5939dadffb8923b1f283e9fd70d7d12d48dc8bb2f3ebb91372445659239a8b39d1dd1be83f82c32432ae4614598e8a299d96c67cc5baa9ca656ee9d55e5e38588023214447c87e97d29858f12a7ab822b2c0de7cd359f38af59d0ee59d28ebc644c03bdc286fa024f8ebb191df10dd6eafdf76b82f79d0af1d30a63f7e6466328da45ea69275f59607c2ec49a6f4fc80ff8964482ae6bb015c33afb92b7bf4914539c72dc6c01e95779e38ba275fd74116af624bc7b01dd0f95ba690afcf9b9dba056e39439133ffdb2d17b27c9c6180b7ee9b129efa468e9d40ed2628319e9e466a5bda720159d5ecdecbd18de3d04a5b1e98fb82daa0fa06696a986946ca744119965a05ffd9ed54f381a038a2d9e80f24fd8e8964baa116d589f97b166fd4c6303de77b0c936f64f31cfdc98f55c4f516aa891dec3adbc70b4603071814bb0fddedcd24371607d6d780b130d3e1344b6ab73721110474c0cd26c0da19209adeb84a9571cd1c269e65bfea8db515f916fc2e26e6e0ad71fdcb480165032dff4f45b520a99bd14d57894997d16e59afbc5899ef1b6b5c816afbc456cd35bbbeb599a77958dab076968fe64698e737bc2cff25c6886017ee85ce704440b73e2c779d946171eb77b730e7861556d672ef58a6aa0158970f6f781b8da79537f0cac2c11d5f85288ca5a4eb50c17af0971674db06a3b346120610da3685c04e064e059bbe9c600dc925dff6f94e7806e2f8bd2504a8f748ae4a873d7cafbe18bac5fabd332567098bbef54b585b5fc8c1be607b1a8ffb56235c1cc6203eb94c1b0b05ce474ad204c9ddcd8f9bbd3a66ff7f33c2b17e98f04100a466f7e1016536299ed0061426aabd6d0532298599ac5104533282489e0db219ca0c7e41f3ab4c6bf7331bfbc25899cffc7dcaa7205f3117c316f2d0015b6aaf093e215de29f6beb33a99044b9b00183ab8235003f4b1b496991b2b6dd5ee65415eebd8f0854d3084fe0728b21b69112f01c9408f19967ad7bd25aa4040371b8d2926babeac747ea83074bac1e279721fbb7ea9e4c44441cdb8087ae389b23b14d1cdff5b516b391a48f8dd48d0b4efc774bd71d13b028b782d57cdd413f3e9bbd3a826de9dc1d13be52c5f4aa458ea014dfeb5a20ecde4a3d0d70803e22157da48992bcf256af7d6fc4720c2feae3511c788344401c694f20f9ed56671d5db67ee3e80e9da95ed1f01d6f934eda4165dcabfba044cfaaf905d76ffe2d221021656a530a2817096a81c4a1d507013c8c1eb603835de9baef3108aa093f56dac6cb3416c8d9cb3a10d5e85d700b3578661f387d9016deabea196fde57bb42e6b9b78967802d2a915380c64680e487e9bbde7c628e7e9e591eac971c9ee552ddf90cda48021de0246f6027369fa2aa4db67a8c3855581d63eea39a45c900050bc1bc002196af349d3c978c695c5395b5634073b09fb08f278c8846e12891515ffab85c8e75822ad6359efbd86312e0d06806f390e4f5b7ebf0ae94e530f578c50646028aeebed7c8fe9a1a0a628b75c9f29c5e39ae2966ae203c3c7bd53d453a4843ba0eef24156a6393b16e3dcea1cb7a5c7809bccf5bf9596d7c345f3c22d903d6b674d23c15e313d53e0c0ddfcd258df06a4b6fd4b8d972b3f2b7b4d97d98b25328cab1e7bacc6dd4051d186d37efb5fc78904cc662b153461a6eaf253f6e93886a2b71c8ee03373cfae8f7c479bbf85968b9a1f2490ce8bced0c63ea57bf2630b4ea2d9e8a156495387619a413a32ede7757d3705c53c25b117bb05a0c9d8073e16c6b95e188f578c77872df15932011c04be8bf8effb076eca19e9360545c34512874c0381cf9d99a99f44111bd379172938623feb923702570cda8ac16a1261e6f443492ac064dad3e331b407940747b1b41cefcb126780ae284c6a7f76c2648b44e4504c4593302e8386e87c47e8a75727311311bda1587c03924a7a007148b13edf3f531546bab5ce2ddea9af20acffa7d7ffd07d0d93abffff464504e6d3bb1379b2d7562f536c03129014bfa1e3ed535b9a7ed2b0123c0efbe2d9fb2ee677ff082e75eee0a69b69b4d57dbb77fa9600cb03949812d7c188c01b1515e34b9cb203162aebeb1a5add3c0c848ea87c158b8462066c9a6dd747798eef5ce3e907664402bde4f03791d2f9e63c670a8b5f8e8de6857c0e73b4b8bcc93a62a3a4670a6d0f71eef846aecaf39000bc4c89ec9f9cee04625291a84ba813cc45e1e0d0df4bd09191f0bb8b9a6d4ae2e3177f3d7915eba6104a8f1db62ea9c20b3000f3a7f4623c4c477e798f5089f6da8a4423880a2dd0f7134832e2bfe80f9393344c50ee045a4a4a9b113eaaa290775838a42acc905eb4d079d00a7cba99fedad74f21c8477c2621a5863109ce671bfc66e0a9199d088051d8cf30df8e6224d2c7a808dc9d330e3251675a9c8320601f104a4bc200d7a0155671baa34453fb466c096f290ceca72d3818f271b91cbb281e08c7360ee7702677b616260f5eb0bcfd8b4282a4612464246f4d825f9754a752b8069388c304b872be21d981321b38881e63a07447cbccaafd9087eadadcf98010fd31c985687e44d090c5c8937ea8e4dd001dc5e743c3acd300a878b61bc272ba2dc44ec861d47d1d94a66843c1a4179b3edc8f1c9ba64ff2ba90d8add23188a9ce99270d929097ba84550462d9b620204e65ffdc5b66de98da18dbc1bcc4445b9a6d860c28ebff14fcdc8341033ba563697a8dd159cabc9b7db85ec29897e31b8c71837eda7d050dcdacee7b77d06cdf4ba849578469d77af9e008729d99ea5b4037c3fe3c0eb759e85aef83f91bc7e864a082fbfb2d0d4b45cf36707e0712745f02b8a895634f67a29a303d2be3fba2fa509079737c841210ee53800e8d37e510b24b23945e4150b3715521bf5916c4b16cbeae59c21b622241155894318090bea3ca15def5a3b3494d92f61d94cbed83e5660d5df082a4e04513e490dc44b1e690f49fe1c75e64a0b519a5ca802cdbef859b8180cfda0f10a13ea8c5d00334541196c019dc0f9eef525d6201f7b0e68fa7ebf26bab4d6923e6341ff84673722f800c9bf82715f7a8fe6258072f3d913183edd11b1765f757fc317bcdfa9db4d6d8c191c1b867062cbfa8b4774688dc13c54d6256e2a36b144359e29039a19a3f8bf192317187c1cef98deefe17ba8cb27c50cd6d7fe9636389780b97da7c100f221e42085397bf56b4eac6f01eb40e1f287b7d4b9cb33f14a3f4df9471ca735be6b92c254fb4d30e93aa952316c4aba73559d7734e50c179b6a5b8d8c77a829af3f0446955212490f2997f8c3b3f8460e4aa25e6bcc71eee0c99d7d4f1c1741c76c5801199086713473adb0d43f284cf43e0f5b62b07f5b3d178e12f6653d4e31c92a9d0c6fdf1f775bbef9382365ddecc075c52255c9373290b63c3d9e28f3eac98ebfb019e95683cbe9680c0e5d7e3aaa6027ee2da8a9b5d8ef48983cf25081f0b82653088bf1015474f35f2315d1340c89813b1cc4101f9546c573e4cda09dc7259c4b55671dfc71b1fa8d68afc1e41ff348330666911301d57ea2ba2e908aee4a5ad4a312c2d7dae611d627f94cd13f3bf98ae5eff94b7f556a522a21abc8360fe5fe209e83a4c0f9830c4e294331676228642955fdc8f18f76a20aeaa0d16a4ff810480ff37b74443bc1dece727ac682ce4c47908eaec3b368bf33906c57166c7a953751a38ee8eb9aa9d01a2d002ff9cacc4fdc1066da04cb3274e525d74378e5d93d3e14ec5c267a4bf46bd4f8961dcce7ca398416298b670092131f8a4887ad268612abdb73a204e621ef4c0fdc0d9fd25c62680d65ac153f899201569719bc6d432b77cc83cb998e719d870388400c6e60321c89f22c536edf872f8d1501c2a4144ab9a9707ee6a56bdb8274827a5269ea423cbc55d6cad8f8c5856c2663444be3567d3a56bc0ed8d94d99aac5a8ab51e142038a13edbf44f225b3c3d25fab872706ba3bfc35b7685d574b39b3cfe58db343a27faa1fedc1a9b970b02efb4548b915cdfe5448d7c7426c0e90e278ab1ef94efd137bd039081fef7d5c4b557b12a30fc2478a9f559d4371502ba2e988f6a1fd6e7cc202a776c4540ad7408c4e397374c1f730d72f07bc5cce4f963e61afa0c1a9f1576c0f698261e3beda703f326a90a410b4737fa65322c0400cbc637eab5288e5262b0feada4821ee290100fc8bf166c0bca83d6a53eafe59ef7247ca25b205be85410ad4e345974b7f357513c853f1a7f6b10fea5b436bf5d5ea711e9f06610f31ef755c60296571b062af91ff89cc50d33d4849e45098b3974021769e8ad876c04b2cc9df41807c62f40ba109d39649ea3b6b33b1441cf98b7aa5db19b7299bca3d8f3166cfcd2662bcfc84d03ceff36943036dc557d11ec954d0fe492006c7684ca209a80d60820b3a39509bb159cc60281c8b8e26c43d283f92a6b6b1c7ac44abe6addc69d8c9d32a269507565ad991fbc479834a003b378a86f537b63b9641309c90f0e8e8d214b7ae1c0ab89d91303fd15361e30014e3bac3c880d677bd74d3928713f2827ae04e308cd81756e21faa22f8b3e9dec40f754efabd3b49ece84409e1cfd81961f02aff73f24f80cdde0dc225ba555fe9b9c8098d65cc9a431ffd007fed33a1b53309ea51913bb63e06b4a8a14c9e5d9c9ec170da43df3c6c04de7bb7d80364087cf570dcf799a84430bc4efcfb95c5301b439d187226d33b98abd01d54201e4657c66883652caf783c4137c79dcf65b56b52270101fa4008e26dc554d8bd2a0851fe7939206270f449f846a7b0b1571bb97ffb1ec01d1c4c8d963b149e7f6b03372e474b0f40b7928e7660f007bdab719872789a312a12927cbcd495876273ee8fc3c80b187cda31ecd2627ba93e960b837a9e2d097e8353c6d8f2a0defeb5f41bcfaf5eaeaae7804fb9ffb7c4257fbcfb74f30e047bb8c1761cbccd4a61f75e4a4156d287313c0637d839a723c9019f6ec38933a85c57696b2429407961a339978aff7f84b5b318c1caa3857de0d29612f8d28d5fc59009f3cf0f5deb1d5fa13f5e9dba8679c9b71c624446b7b9d3ab85e4bcdaea0acbf3b0cc7214a1cda1988d2b587d71d51573a56e6c5159e30fd619fa451cfed2703478b03ddee77112ec30fd0656806abd4218c7c45b680a99488cafd623cf51576ea5dd1902283a987ef0d6610d40094d41978819890135e441b0772d18f040a12dbc8bf60708c998451eba799ceb2e2c6b11187478b6b5c9806138ae248dd014f09aa4e7ec9add1917efd1b3004276680acd89dd6da2d4df124cd16abc9768d22c1fd9a2ea21b9d014143f91a9a7e2f4f04f98a89996c1db03bb2d4854ac2fb4d5fdeb6c8b58f9b8296384f317575fd23c4a621af07fbd422ff323fb06251ed31631e7852d96025ed1b4bb3001ad2bb1142ae49062ea07f966911413ca2e25ac78686989a5a09e1871ab493732668246ad259642f08cf952a977fa599a1b576629f8ac07063972ee5459ca5298f502af14d05278efac3b3f2c13877951e76150017a5353d0331f74b2dd37652e9347181b2476eca2fdef15ce60371f483a0e20a7464064c312248cd666808548051526093b10671bad242f15baa92aa8905070b05003644741057a850131a91cb647b16222c9502305157423a8209cf2cb8c0a2a147c51e7a73f549898c8ad5981a4ea10f7c64e7e22914e1a4ab7dcac9fa264e45e2581ec69ab57a6088c0992bcf00bdac192cb0e047e60ff6ae35f95ab4152cd0de58302820dd2af7574c5934592885366bb4b0ed57e65715ec26ce968a889a37d1f1c9002a016adafcf5abb67e7f1843877e071e12eceed35de6d925f90c29a39910cb2cf9278555e4436238c3ed2f1b2242278371305ae21005c0fffdad67592ebf27ab89e6b497e47bfb1a17169bcddd11603fc3aaaefd8cd28503762606c7132479b87a6db3a099d182c5efcc463d596162ecfa197a900a281d1275c14b4407ed4d74472a543d6957d1b27dbf9585b0a4374bf12c197e37e7fffe803b126f8933280e886179c2d4899452060966b70f7db68e23d030f83eb0981dc35396a01f52c9cb2637ad69da9b574316051e3a0ab87ec5c6d7a3a37e89808911a3a71645b189ae636c34056fd1b019a0fe3b7d088a2b517f530e96df90bb43c76bff021e03b6261604666728e8d4394c66347b0dbe17fd318b5930b3cccc6e3dcf47fa904a381d2b956f3ba5e3ec84fd1ec7b1e2295d15fdd87453252689f167278bda178ca70eea89c528c96c315208bb84b17e269b77f762d9561091bca173b03384fcff50b303893ed841d3e68d6ba6e48945766d80343ca82dd9e9a77741bba7ef1cf29c86844243681be2be7660861dd97d8cb839b313a04e3916e8df31178109d9ec9fbdd83559a9546400f748703ef4d83fde4eab9ff72acd2cf248dcc31bf45734caba07cbd299a50be1520a241b6e0a4fd2203891092480702f81582901ef404e51354546934355d7ffaaf4d860c067514a6072d3f03da5adf8a63c8c8f77946718b2ea00caf1808125e678449c547b8744fe406ba41eca3d4a23dcbbda16c19553d56ca6bc59a215f929cb0f5910316e0c0a549ee5a51da32d8eb7e17c251d32b7ccd6b25405a8c55dcb8496d1ba5c9ec8ed2b0885050a2ff38d505ecee04f2053e4498bf4cd268571e2b1071e1f49d707ecafcbbfd3eb6878d18b84e69da29cc86ee597f9bb8692d83ddcdba7dfec9a9ff1a4d244204a361e1b68386cc65aa57bb90103341977cde03b0c7cf1458ca4cfafae6cc84e07105386926c1ab99ccb16e6f3d329b682665c29949beccc4ac802400998909bd4d8ebf38428a99809cc20fc59b0bb5a14849f7d765abb97cc948aa1050193389974888f9b9748b5a72141080562750f81aae289957b8730e00fc1471cc33841dc105a325e7366481208ef9d3033da743c46a07122dce16d6f6aeee72b0453c62b90541887a1b0879193dd8a670d55e4053e3ac48a6a4f4879a75488f0d7f1e1797af6234e24c035434e7ea42fe130ad71aa0620e1779b6db960891c72a382058e4e6bb9a289f08beb2087dd701411d89ae5ece9262607b7fddb643d69736abaaa02bde2ca255f12521557d9de6289d0094dbeb2ad206515ff74b9fed0ef81240d5443eae5b01e493b44a8588e33ae9add2a36136050f1074eeb2e8ad84c72e8ea3faae62e2a471eba9ac4c9ddbd298bac603a233b6b1f0faf0d5f474cd3be14a339dbf05bcdf5b6b0344059de2a59333707b90defaa36d3aac48bdb81506f581a7918e74c8843e512358e93abf55634407352fcf5869edb6aa9d6445275ddc1ba5c288743ca62213f533d7aea5a4666eaba8083698e2bb4e725bf5279df7a3a43d9ab4ad5d6ee3087ccff83c002b4a0a6877545ec4d428a172de0fac5aafeac079e9ef643b594ec7d69332a917fab180b8fec4380580201f1d48b84fca43cec1c0e64886204293669759909282f69365a9de88953898e4cb5ab15b3b2a7735929157cba9d0d99c48e54eca73a18fafe83780dd3b82504ea72ed1e80e8d6d11817ac81d2b975d3071fe65e7309064b08e8ccf792311f5404ce2aecb610444592404c21803455b49d1e26a6186ec5afb2a767c8993233b3c10c5ab05003a90d1f33c17bd9432477e737b2590bc5c1141fca41663a7433f6b594cd5173be94045dd3155a68d8184dd0315c992fd7695f9f6037e819f30cf2f10fee871842c021b07db9303b793a8ed2e725e7e195c503b23faf14afa17e0d1d32ab88d74c46e15d8c43a613615a662fc0ef330171f4d6094c78d8e34f632d7464412f39a434f67978a42490ebd54e2d9bb56b809758a5954b0c53c0ad8c30425ed94e469e3918cbdccdd68852be6318d52010578f4940a6ce33c16fb4f41e9af298f5b9a20b1e5276ba81a4bf43ce675eeb2242a6494dcf142c9d5022ec0f133c8c530e71d4a8b65d1ac4cc6cbde77789603f5107d94e5206fdedcdc6df429737897f53e005d1aeb23c007577e50289958d87b3684e7a18cb21149b71eb9cc8c8b85a1a1d707ccf584a72e4136f58c15c96d55796a2f3b0b0947b237a06dfd3a2a40da06a39fdae5e4ba8cd0d579ec2a54f05ae028d1edf8ea8c85022a214bd3b4e7d771c3e4463d01358a7c23ff5efebfdd70b538638eb4f47f4c59eeafd71edadfd4f19f48fd0fb9ff9ee4ff440a80496e6a72fd7b24dbc9e9caf5fecc15ef7958efa11bdf65ddb34facf52448146182c9267310cb223e260a9db5069677185bf48fcd6fa13104147d8a1247ef96a5b93f37bd93022a2d8739fad2d06d2d5500c2b775d37b2bf648bbadcb41ccfbdb977276addf1afee737263efb0b3b435653984cce7792329b2473964afe6c9142345d82d29c9446df89c4f2e3bc513f5d0a5107e201130b3fae5505617a2bd41461446c628b7888533511e72ab1d3ff3992b554972ccd5776bae0ef78296af1a501a5b59c8600b12082cb5464613cd156596abe56ef253d7b65606a7bab29222594297e817929cacd6529ba644c290a38b5a5e82adf30fb32f66104252d0cbe6d6f63ea513c67c4fa3b634eede7e608d056c8bac1ffdb01678b3372770bd086233ad905f177addf1abff7177906113fcf3b845fe2ff3e337cd8bfca90498b74a43ad34e172e514f4438196bb2bd86251869c0826562e585f0d23b8551bfc4440b7bcf8c16ca93450b518289d617f1e30b80e00d2d6752ac180f325af15fa4f9f5eae906521c8a21580e579e8fafdb8301bd818ad9b96e837ec94663f80af44cfe6ed8b47984da3a4375945ddcee20277edc120ef87090fa5302259450299526df862f4bdd5be69205a35549a2db6c7907200c848bff1f5280de8106f23bdc1e8430e83a13de40c1d763b886d1687a48e597519a0671b727c0e030d0bd906613b3cf870eae20552cb2ccc7054580d42a427ae6627eece68878bfe7e7a06546e6a6d454a4fd97d839e625463ebf87da48f10b8a33ba1d7cc049e0e94c1cb574ab127a0849498495dc4adf8e20ead9da6ee8d939c0b384a52e14aeed8fa27b51c6043febff3417c0f043a7eea09aa7ecfcb942209ab2756dd0a578019ed0ac1e7b622813ed0770821d33229cba910fa12cc6a23894c15025454de4dce43a3755dd01aad160dd9d65fdba7a5affabb32d7b54832b3335e9ca73ddbcc61b705ffabc8c6ed4dee33e49b8f1109e0c91618fb260ae0926264f0ac412e594e7bf2dd2d0f288f8321fe19eaf05ddfd2f8c84cc6e319389750e319aeb6cce3ea13364cea2664d50b554a8c9c9a3057f76d5bdd595fb6ec8750427150ad6bf6228d7335d19b8c97e3e94005d19483c04dc178bb59ac63144df1aff36e1ef0b1483bdbdf7db9590575da39cc4911602a8b95a2e0a85cd577288d683222d1212e4388058136becbaafbb462ef363bc3b2853f4c0379ac0680ca8c60c1e8344f80c8eb3bf8de85af74cb827052315bd2cec3219a964db4f1c1f54d6d29034a73bf93dd8180db4d84ccdad66e42b477c8f1171effff55609895c773ff0ec640f82c1a1a46c0a27d5cdb78db0b7dc5530686f1630a3a8323ac98ccbe17bdcb3ed64d8e55b9cc8956e88301c8179da84f75e20a289cad6c232cfa4e5d0f8995aecfa4c88da240bc35053454722ed3e417ddc8a8a151881a071751c0a0aa07e95c1eb71ecc6590320961f49a3db9127f5e1d253f471910dc14dad8157bfb0509b773cea480f18cb0428183cdfdccd1cb127da0748fee9480f4cfd3d0cdb056d26703e3dcff4a07fd49fe5145fa3473cb77e9a20aadc8a08f45337fb261a4552a7bbdcaa514b8257f3394a328af110d940ca1eefc296a8694f6f36ecccc7a4298a78413b279ba09178174599a8cf0e706d71698d1f0b9fca45856f8c2d3fab7c16ab6472ec4d5dc0b799c796ba910b0c67cc12af50c8ca359d95ac59138f05ed216ef98324b03df94b8129bad5dcdf0088c85e40dcb57b785b63c211149d1c0095143b7473295afbf81f572793481050fe11e1834633fa57bd5f192576930940f6fd23c496cc65d57f0b974bbe15b4c0269977eb5129e55127261ac91ab1b16874087017d5558902285e048a46eb9572129c2ceb425dcc880ea72c3283fb2012406369ebbd6633ce247507da4042d077bb36a9545bf548829d951fb3eddd05b53aa752aa898f6ca007b44fdccfa8b57354f02c5ac5e2a7007faf2a26c4f73ad129bd1b65228172de0e945c3d6b40825f8d790d56948998513ec5a4ffbbe0ae984059587fcac38a60f33bc39a1c398c799d6a865b10570cbb92595b3dee238b87d422903edf9d0378f67e64006c23cbe070d1cfac74458f07c0f70cf69f9f74e4c0435e41aa432c16b3f5b161e63f1ab45b77d865464aee1196d551381999bf9efdb461dc4acfbe806223e67723d3ef8db4cc8a1938027367ca65eb7579474b0663e269cf33ac24660797a8fe4b4f4f34fcc23a4ca9587bb728a530af36b5aa0bde9d0128c9957f05f655735260bac484e2daf3fbf112ff0ecdd826ff21edd75391e46316ec8f377591e8bc925d837067b296f783a9a9483b39a8ffaef0897a034480b0279a313c6919731504593f4025546c3619bd7e785f65b317824d38aa557764b0fef4dda446076e6ad0b88032061f8a82b414a2159bf358ce4e799cd1d34273ce832df27fff80367e01d029010ebfa554ed343ba32fbca194743f3fd273b6e07f1370572636495354667cafd054f9c4075b01d693af7a0911cdab8340d6f10e877487e21ad6ac9c8ed6e150692b0930c00c469a15e56c43ee50cc0de24ad98e7d3935a963d31d4eef90c002c76e431081d8ee1bf1fbd8cdc79bbd4102f2eede2c15de6cead79022eee5240108508c0e2634c6c662e36e24be031c4656d32069dc78187ff7ae68c3e68802a4504087f9f9dae8cbfb7d3c8d8e0ce8f6e7a2bd0a4611fb76c2c22dbdc713d390eda61ad128a518f4a223155ad3f16c00a20ea0dfc0999962a43dc4ee4ce232263b750eab23fef9692177d576883caf2b269adcf6cb59af547afb0a2e1e24885c7dc6fdb11d7abe2995d70db48f2da3373a8e51957b2850f55a58f631fb81fde395d63dcc3e5a4584dcba714aa47d70bb59b5f08108db9afb382126c584925d48fb3e32858d1bb48a4c3b0923b5582d91edfcadaad51c3f5aad39967695e34e318d6eade84d558bb10b88d64f7314fe85a2ada031d77ff4e30846d1b4c34db6be8fcd347dd4b3e08f354dee7912b6a31d468bb2a6301304107b37d963504345dc0fafb9d081fec6e16325d68b6a44dfea2458daddd5b232451b5b4643452b342721c51ceebd21f88685aba37a3c75903a77fba731572597899609227e48972f05c2afa3863fcc631dcc10fd8e569c957c62edc1998aa1a0b126a3c9aed64c3f82409e4b9a7951015b604d9dcbd6186866998da3add38acfca9d1bf7b77d460c623f0cb345be8d3edb62c94455ef5fac4ee958e54954ca12cb904475d3c14102670e1e367a9c74431d891afdefcae9085cb1b3e6411064aab6c3a6e04243332a57a7c9c23e2bcc1c46e897f56f0c0bfd2576672b6befe5b31d31c42ef687943c35d84551ecba839bf1ad85fd7449845f24b83bb1f099407da91647f089b9283d9c21b40e0ab211d6a971710c6f7d3bb75419d45e2a7a4c06a2539f16a44838ac18a15b472a8f38ec697afe0a3c5b099f18a12ab36d3e086a615d8656652992c2790af9f5c33a4951608c83af93c58bb4e51203b134f56872fef50bb2524a5b8460e486c01ada9114ad174cc9a8fc82ab5d68d381872761c82435b0bf705e5f7072827416fd80c1e2751ee07cb23ca2b4b7bf88d5f4e0571263834ac8d091eb8ee9ae38f748c8ac47e16de8fe8dac5ce3e9e6ad68280ba880228568e08ab4400a61b1cdaac0c4038c82a26c9d7a0e1cc3a5342b42c631be24d3ebfeb9f28e6dc33308ac65f0417a8d634c4a71a67ef004ce7cf91b11ef74d7dcaa31353712d8c128a1b9b801309cd6c68dcab869a1f2cf2765ba4ff1b42a83740949ad8a70816e637f88d0a1efa4e147caf7db6c48edacdbd0a711cd1eb065a13eeecd9cdf32c61160389f2a983fca80624b45e78677429353639820a85f381f2ce66de4d717cee73ecf70095db0fbca4f365af27611a6944b9f4d2cd596b0446000d08c48015447213309984098050a51dda30c10d193c4903ede10a26c106069422df6e0756124b878d0f72bc152b4e7c213b4b4cc4f25237ef5643415106ac7857d660eabe36e07d6e2e725c05e5914d1022258bdfdd14274afd2608a334589179ae8210884addc70328d630ec639881766cf426a073415040c609ce35c150d6dd82b060234e6888ce7c0666134e61ae0b76e45d9694dbad71b64848b902fd0e8750c21f73e5765deef33b3be5870285f09e881be2ac78316fc0f27ab87f4d1b57fcbde8a7c4aeb6c2def7fabaf4e4325af6bc30b27335226261c632ac45a2c7ff392aab31fa1139a85e5a6aaf39a851109285275da126a4f821cc4fb0b041db040ac13d20eeda3c24e26823beeeb54a41bacea9273f71a64e92df353d23ba6ac3420c158af892cd28c4d57a7549df8c6ca898c0a89547a9a5a891a788d0bf8d4799d65a1a80da7a3f3fa18a3fc3ecc80a43a5957a86d3568740d9cceb3f34567878e2a69ca4604f6ebac7236553b74ada2bc8c109eed5a7cb8430520ee25d73519d090a14ab1d977afa3c0fa5e481cc9cc7d9bb6931dcfc6681c04095ccf0bbaf251305b6f1946589b122dd4c5a09ae0e5168a83fd339ac2bed516dbf0b5cc11c9ca5e94cc22dd771b2928bbefb11e18b4d29bb471d48c16b34628425cee88a8fea506dcca31322f42df5aa536b07fcf6694f2c892cdea6aa91ecc8b1d7506038fcc52efd266cb760b9021c578a60d85809fb4d639f0ace9c608d274c9d6980e162e891fa7ac1f21a59961f3ecf1613713307cdf9b4694cef7bfbcdce464122aa7e4bc539849f7a2598facf5302549df7bd01a06d4684fd65743818c5e6d1905b0f0caf024c648efcddb72adbf3ce494cdac5fe85b8086f405b9609c769332fcbe69842343ef40192b6f9a998b322628c1ce2bd80cb86b5205829580c36f1e48e887af76eed8c32c52851a68d5f16b461d3ce473825a3a7c8b079bc086ca5db0671bbdb3201f1f27d41b84259995cf3db5e533d9ae942a7bc659d4db24cde7d1b7f17b3e54e917f6c0667446b46d64f59a3b46c3b8632754969330daa5d8e6c0643dd031c9c0f212ef26b32e66b62cd2330c6cbb4551b477b34f104aa14be0174416e59894a431fa21b2aab72df3e27c3483883c5ffe22b3318f1fdb8c15f09a13dd1d54fdd72e6e280fabeb959a9bd31f9d3df67b9d56fdc1aac90e5a25c2fbe733948e1b35f9d291d85ef482bd624529e6104fef9e8fce5401f1ccc043331e720ee40c1c94d2053126e67be42e14703e703d03b79422d3c4d5c29e760c67a7c81975af6b6b179c9f41025efe199b1aa1816736247182ab2359e497e0e0001e8ea1ad722ca3c50ef67ad1b77f98831da15364b0121033cdad6857276e2295f06d60219275a0d6d26058abc189842c1bfd318f710d2f475743f3a24824a91add1bd46f448fd91943b6801ea3ced03be17fa20b76e8dc61413bb3a8bc669458ab518b04e2e755299e66fa52faffee54a28395aa94f4948589eab1f5f5a121dd123acd2c2960a2782a4e2fc4ee08793e4d6846a97e4680b888002a1a00b3ed4c48629be43bf5df2c9c816eee39dee36b620ccdf952e58524b0451452f417efe30bf78528b3eb2928fc15bd362074e078f20bbbe9c03e5aec17a9bfcff87b900a5e2dd9c74764d4fbdb19cd99de9d8b48646f16b4de2b5498bd6b03c16bd9746aa20c6d5166dc16eb7254a2a318d27e21d5b2751278c6ed5a98a2a0655cb4a1bf9fca8618dace65a6b15e9d170797aadc8b8425fea61db74dd88f93a918d6640a4bee79ae8a780d18988e6d981f38bb8f76bc2de7c6c4a54250db65634049f5735b08be52c2d792288608394f0371d85437f5a01b003a6a26faf5ed9267aedc162854f3c1163d153e336062b4210b18ea228821406d851351589c306bec4b701d0c2b5ebed13ab1f6ecc99a6c3e1839a761ee22f943c84ec425c84c0b0764ed94d9ebb2bbf1dd2c20079c314ad58688238a933653be902f4e7e9d9beba505e31b33637cf8af2c859dc57ca0a26bcf81d03df4ad9831d065753f324930cc1a3ce00096e50b4450932e7f243e0bd290728a8f10ce942d144bba92241b01402a3ee3600859aa4ee71a4cb9d195ef390e90103d77c9ca785dbceb22ff7117fb63e1155b08e1e7527ad2169e3bc52ff32dfc33717eeb58690b49c5f6234e939f178316559c45758fd9c97e5b97ea2576d4557996f1f378d65b0ad179f2244891486a4a647aba46e667ca338a2b72ff8c01e4e32e39007e518250e0372fc50e0162072488d96a4ab10741168026c563919256f25bc2919894d8a0ab57272670185b2b2436b1cd686767d50b2ab76746237da81657a57f43b9ecbd182c712771dfdf40e3dcdffe3d2aa3b753b443e3a65fb926c62e59f5cc0022f458913cbc1905f42ac99a4f97905bfcb4f08d137b11f5e9b1c6e182926f3e67a178008b3d93be02e4f1b92ca471eedb3245c61b695aa688328855ddf99a0dab69e48075d8544712780731f2b19a514ba9460a3fac216be0dd150755597bab2c4851d7e86e499cc53c4008679186bccae19299022116ec31deafe84fff6692b4fae41fe6ad6a0d0f082512caec39103ac45284faa52e8d150c8b5d6c5f2b3f94d6a2dd3311a0832059b65d16320e404860584d8939a77731ee8956b40feffdc785841489d31f791044283af9ff625c7c5446868200d7943c7a06e17e291d5005b3b0a448c36efdee602bbf428dbd84c053de07d65b2a829529121499db72f87de55b573f6fa9ba16da80824756147120666295a44fd007c992279eaaa3561131ee5fd40cbcbb04b7ce3ca209a2c3276673e10cbc01b8fb2859ead2235b8b7850a52f98a3ac2474762ee7e021b7b46f94353696529846595d0352b999b8aff78db8faea938d0f42877bab648b6efd022af6cce996fb0dd3acb253d6724472f0397b823c5c2973745cab15897f28431d3adeb0db7359b8a6c46de1b854a9040f31282383fd43028a87da4795a1485093c99a53c43f008e37a23aba9d76b2dbf558247a3455a02a622ab7892d6bf5cc7520998d8a5e19e5893a99a43c01fde5c92afddbc98c44ca5ec7a3ebe388005ae05c26d1e94b36c6f292cca89893d130fc87891e4882e80525842439c2237dca3afe62113d9f5455f8884006a1256c11d954031a4c428d6f8e46a7eee44601dbe1dca71febad5c77b8b894d257ae9ee490822c81d84b3f77d711c1d8037ab40c13bff2ec1203dbcdca1def9bc5259fac7426be7e19e3cd282bd8bb43d6395f548988352bf9fb5232ae6f0bed64743ecfe9efdffca8f699b3b10c37aedf8448440fbc88190b95a16a7d7a00c7f6ae3930d30461b8981147b9461e72e9b2a2049f71eb7f2aef73f326b3ad5f099210a5d4afff20f7e3cdabc563e954a96d3d03a530c4ed3e4ef3506d17b12f14695473501998ecc61a1534dc370f18409be1d478f2b26bf0e752669f80d8879e6743995919b46f7d690b354903586858f29d9a2a5f9c9665edff94ed8f414b91eb8917741821f0e7878c84178ef53514973032a70d9d63955f3a39e8776fa73d675f653690eca16cb46000d2ff2d1f9376e057e8021a8811f1464df80654effff26535316649f21dcd8b80a13a3f07f45c269205747141c2f4835ab181a0cccb3a0233e341576d62c2ce1b0b7ca50a0c9a9b4d5c4f179b3f135c1a858ee50497993080c85ff0111a34480cc792c3d63b829a923a7623cc9b3dc3880ae87880c34b0893100aff71a5f03a9f0ee28fe1698dd2c5280218422881df0f90fdef99729f03a98c0213fb54ca1b255de71ed50aa2150d438485958020f997bad22a729c65698f0a75dc637af2549e82d05da78de22b249c3c5f15b3a5960e7f3c9b69a936f51b75c85d7cc4580a15841c494b1fd04c5e7123584697e94c496a9b342dc0155e311d148201d844e9181b5c4d2e279282a0cdd8ebf36c87f62b17ef19eb0f06d74c4857bcf5619f178ebd19185c22438d868dc6bd16acb0f4245f7caccf469b44b31b9851c5d4f6816968a8ae503b7e6e6acdec0a5a9d76c7a34705624dff96f4067568b741e64d558febf7670388ab44b8abe9237a2abbc70dfcf7344fb9de9202e899bfdff0d9fed8e4a8498e6da0b9d2dd63642db4b4bfc30371353c8f0ef9ababaa2b9d57c15aa58a3255fc5a3ed664fbb139aa7c6367941b8926e7701ef1895a3e20737080537fff6440d69f97e9431b5e89f651c80b8a6c8922b0eb9ee66557934371fee11c1ca557ec19c33317142b8fa64045e67c7a1003146a5a418074bd60beade0c621896d4ced241840a3bbddec5453b5ff221f6629ae0716d4c5a7af1334913633ea9e4c5551788813b4be994f40a0f1dafb453ca3b0d01a288480afffb366f8de39ec419824dcdb73a62b10b6b299849adef638f1df431b613503e41de43e54eeb6882546bf936a8c5ca836219def44eb16dc1d99af385a9c139b5df8fc97494fd2236622fc8068b788f0bbbd1ab087bf980f58b1eee6c5115403acaecde7ad30a17854cefd21ae538225951b8cbf9b912ea0aedef1574946c135ebed7eb712a256f1968234d698a6b1876e25565c177323a3e898eca2d3ed3905e33b35c8e89370e9bb6a5dcd0060cc50ee1fb9d89a60a8adbad15db5d9d27c12b654d26626980d70576bb4f0bda6e9d7455af7f4efc229297411f136aec2ea96382003b3b329ece584159f7522d457ac7dff54080e0d60601619bae638e85fa20904bbd16ed4f26bd8ba077a72224157ac9a295d5b84ec6b2bf30cf114d1aed438b14e5a12ed75b6b62b2ebad237e38ab3f50c11c7d3b6c6ea60c281271dd7c3401713a9585ce7d01ad4e150e5ba65f5849de80aebb84b8a0474b7ea495041aa12a08e99cf3dc251cefce881729eae57bdce5a177080c62f0485081ce053a1c2d81858179ba95513cd823d8c47fdeecdacb22c911032e3ee6a9904592e1c76c127f9cdd60cb2becd5020511caf4c8ce0b39a5e35fd53c5cc5382dae21f080d5f6d0691111cd2e62b8886cb859cdb992471f7b071961ee84aa643df88738649da72cf949e05e7101373f58f4c890d210428ca9c2540e34a123ee508b241f61ea51c10feeaaff3034f6c8c474fd1a62d2b4966924481242f205f72d6ca53da6c956e0e541af2b398b5b7c69a6a5c1474755f2ab0d52b2468ec2cafe06905a8aca6dcb2e596431b15b16cfd6536aa31927f07e93f1f6056f844d6907ea8b02e245c805240e4c2b2d4896e4cb76c865d02e8d8b90be510bba12d981614935ea87c7ba80f53d62b68ea3a4e03d6b6495e0e444b318b957e6299b966b731a842ca33c4f00c54bb48c60570ee7a9dd74c5ecd2fd35322688f9978ca47b469d449f15fa052c93be97728f4d7cfd980596ad7f99ef812e960ab97e660f363d7a30fb8b793e801f93fac3408e474df314835fe1ca155be3dbd21a03ff53a2973cc7e0d88a460e8135c0622fab4b8b0dfb2072293c0b9f23f6508f0c16ea3e9c3c83c29ec60f216b97f8a6875410d1f468fa06a52d820d8de0cce8142a7f1889824c8dabcb13af98fd9a0b079e94165cfa56fff2f34b965627daf9ee88ff63d43589f354c904f08e096c94f22d06f7f76e81bd613215af973cd77017ccbed42facffe4fc11a71e7b030e857dc01bb8d8581b03014dded9541c13376ec8d6c3367a0a8b66442968490bf8eb18c703f4a767502aae122fabfa877bdf00196722ecf0aa057ebad83718d094495ee431334d0c0f41ec10fc3d8d0db53c59c139f564adf26cbbbb98aedc84a334d8633773edfd838990c75fb91976b68740583c6abcfb6228f454148f6934182911ebfdc5f33f01159300ec3441d413ffd7f2fe5e0161b06cf8bb6b2214446d0b2cd5bd80ebdc72ba1dbae06d52172ff0dbcb27e2521ed42954d990321fb3ff6f96c3be80af589152a59ad383ef24c82ea7b10e20424182501c8fa4be7fe4fb64f2818c92d26299c30b0419dd885ca3c1004772c62e53825d1d60656f9f2a52425d01755220402e4e399b178b54a47eca4938376ce6352e7f368ebd0c560ae64a14be03c0e6818170df6a22186583689a7b582b388500fee426b84b479527cc5b92d18fab4ac51cb81adda7d7cde6b4db5a2478f1e1fdca1e09429dc9c80e637a4161f1cb3823a8d6d20262b2a1baa79fe3a3fa25debb2ed1381c6a0b0f138824e67e665a7e5005104bf9f9a82779a2190bebc2cb07048ddc4c7e704cbc88caa6577983210120f84dc23cf24ca05a58175362d2d79f7fd2c1b3178b4910a5e4910bdf0974c26a07792e75b38cd5aec456f1c510edc902e4adac748cf427452718cbfa111221df0b12892189d12b062001fc2bf53949be764d4a6fc8c5087fd0ccd47a3fa435e4265fd843799d76405156bcaf49d7395e82470a44feb398464285b35a25b34c3d7dc4a7339e21411e896cee7146049926b9a07f34af8da3a5422abd2cf377470e9988c52a5fd16a2cbc0062863164936204a192503a195a3af61e3a2fdc2e95c71246d23dfca6ac5a8788ba5c3835678f6b74363f61ee8159f052580bdd80d705bc4006ecd23542a58641f5c712b76ef4178709f203354a630098862602e42cd8807b36b3fe608d0afe4d8929f0056fb3c8f262a0bb8aaba394f288fc144e62e237781f8e9e16bcca068b1d078383b50e00ffd916dfae0aa7728393d5a8674cf1c450072f5ecce6e69e92485c32e36df1e11403586e948aeb5b82fbf2ff766862d3fc37eedd32ea9a371d97e07f90f2d7e0db2e1b51c2bdffa0959bed5678c431acb15f920ca50be0f7a6eeca5e735a4915df9ab9087753d099456d0210a171e5e4390ca7f402faa79717f71fe9d8141f1538a31b43eb1fc2030c0cde05e6e9109b849c07b8da2a4786811361d6594ef3c55333c616ec2c61e4acd1deaa4a3dcb423685dbd80b5b9d8231912ae62d77677215f6d485ee2c065427a203e9c1c99803018993712ebd5b6d9994d3ea1292840fa4e003281ef32dd62d62d535229fd93bbff0d83e3e161aac363a7fa24c3a90e4eb2b0507a90bfc0dd42977d741f4971e50e9b4a4c43f7a205ce3720a62403a10fc28501a72d00f5f89f04922aa4d90a4cf6b4318d4079d74955b8b15503571e444143f10053ec396d9d7b32cdd9b4a18ba97d1162501bf84a412c6e73f82b5d4df791673e17411e7a50617664d0b4913bd7a2800441614ac17f94e4fd449f4d200392b98436f5358d90ae7609631a95f4470983d34f987ea20724f4062246aec92711997e937d956f280521f4ba04e3cddca8a3011c5d968a04b74fc548c6ca2755bff84b9d5665a3f46b6a50858ae6050c22a1eff6baa22c003800abe3328eaa2a0aa818307462051f466ad7ea228597dba08eb3b560cb1070198f477805d247498ee0c0cd2264006dc657795ee5b8923dc3ccb213804be86b527bfe51825b759a369e418e876215205fcd78ebf5e3836c5f44edd6ffba20247c089ab799550652c9a1093198a6c73fc7b7087b1d0b96a92ab6bb617b3cf8ee43e51b3fe4af97436a92e5e08ff4abd3e9e6b31c4cb54b721be6f735860a4fe942a09c91c695a66d0ac8fa93ba5646487ac0d41a57fb5f44e36fc37be3278aff08911d42f299943044fac4560d48a0cce7d2f37c581f069183ea0378f47eaa3a6f56dbdc112e9a81909907ab18b0824f69fd57e8d3df1be730e02c3ef6f9f34b16ec30e6c846136058630598265121a6c9a540a659b435014e3578dc04b91599290b4968db91a170901cab1db1b081a4e3d99138d79b666447126c1fc96454bf8572b411058fb8404cae042a7f43ae57309e11a703af166e0c27f4cc406eaf218d5bf05ed2b6abcf54389a771a6472581741a7d4870c44a8c4cf1e330480622950413018944b689aaec97adf062c3ad4d61782e0de4c03fd6fd053c94b6b7bcbbda59452a62465e80af80a790a32d589f6fa5b468f2f43a78f2b3df95284926987c180231541f68f079076a264e832e2f6302218cae91da56ba126b7e75991944e9d62d790b203d960c7c9d7a3ff79f954c3af57ac63d9ce665d6049566eef4483ca29e5cad620c162d8281dae732587ad19b0fcfa9f48ca4e6bafdde73ba7c375e4ca088e2fad865dc766b8cdaef400779d2cc560558e03246a804413dded8ec41442190e796943d528a5b4562b745eac9cc1560233783c517c708643905002f66438e46507249a0d405ae4862cd183cfe7f3c17809966894e110258c702f3e46a02d4c90388189361a8d4626264390d829c9700812454e4ae04219b2c414a5212f354819b244eb05090bc689136268918390446b2fc3212f5ec8a4f6621228c8244e8bdc90249a40f16c3cb85005c3814ed26077eb709c8cdb8bda15485e8d46a5c4f89d618d13682006181bac07fe628d345e831002d66a86025ce2a1d6e7919d87fa45272a1755ed756907272ed05ebfb417447bfdd0b5ca76028de2aa7b17c4dac82343808757dac1737c08647b8a20214c959b4051e0cfce582d2620c3464d2b42f5c33cbffe4743870c6d720fa193666ea102bf3a01a20800bdf811b6c4585f390ea938b186ce4b4fda19018511fdb6ab3419be10d24ddd576732fc2ae32923ec4bcb7901dbaecad852ed76e83c737cdf892f671a1545a73a175cc20a5639fec851c6e4289fc89106214792a7babb9210eddf3c5ae0c36d02de559caeb654ce23cad9840ca48150a0f90187b847c8e98294677781bf4cc75971157dc495cb99edb4e753a5d39e3b8b5563164406b1346691c6d805a936ed0969effec85eef8a45ca745cceba5a85646e96d14b310ae75f1f319f989b51272084106a78f45cadf66557840dbdfc226a0bc9dbe7d1e20ff1df5fbd97fdb3637c7fe5595763f6c05554a5a2aea26fb9cac92ca2863181e1068252161232b32ce444a82674136a858884b0e814094c080634599c7105d3280ddc55b41ad63231bca6510ee33f1d355d60cf37f5c4557786508afef38f02fd05c205fe9c15392e8adedfb1889ffff0c35cf29fabc8dcfe732339db7f7e642b75fe2250c90b8687d3a135a6c6d80ab32a018e3029a1388a2b6f67bd01c31c5731aa265852c376b02318fbefae2a4735cc0df8050a7f4f114ff6a5f77401dac86080b8cf7b389a459fcf7efbebf93cb6dda86d9f2e9b9f654f3dc74dd1b1a89cbf2001e2838a64577b9e3ff1455b07db137130d3ce1b874516fc0a0fa806b1228e768e13db80312c671feffddc7bbf23ee9d317e9671a797386352557b37663d9c7ac419f36ff6a715ad9f67217f978bc17df1079d1fae5eecde9ad39ed6652f6c8b0b24df0f101d3c5faa5e424e748a0d787eedaa4e8eb03dac7393bf98153c559aa5d9957eb02f5f0812dcb9cb4df7e57ddb411fed98a8daf38c6981ad105bacddb68f2a7f2119ecb4ca1ad7592755d81a70fc0ccbb8538f380343798c2bdd6813158cdf61f30b118a8821621739c6efb0f9e7fbc3941f6d016d78bee4ae607022501558f4f36388fedecd25862886a8487b7742e83ad074dfa52abb11e8bde03e60338cce5fd0bb5fb917cf8104b88fc411aa960a83f3d7731fb03946e745a077ffca18f7ce20f65f704156b6c5be88f3979bee57eefea553ba0bae5c98b123f8be2643953fed419c639cc30d0753038e4fb9b8ed307f9ab888333c56d648af7127d753b86fe486ec5ff27d623c5c7c142efec9911c9fc4e57c3ae4ca477bbb2b549f80a36be5302b579665990f0db8a92f4fd58ff647a7a20592e3634ae0cffec8f113d3d9fa72537c7befbd407ec8b4d8cfb820eadbae880bcc09b8c9af7ffbe474ac94204495678e33df0542774ab634e018b7983134e0fa9689d69c1f6d66fb11e86410a7ff2361ebca424fd0ec434e34aae6602c07675d85a92b9ce1f60346730c49c51a28faf01bd019f094b2bb5684bf2a835fe2ce85749fb3542a676166c0dfe591619edd0a3382bfbb7a92cd6576a09dcd07508e9b3e40da7399ec3fc41690e631a06d871cb2b3da9b34edf98c228a34998365165a8cb144e6e011548140a20c937ca89495b2aef4837dfc4648f946e0b7f661cb0a67d859ae42018eb9738cee892bcfdbec6b0633ce71dc9475d991ac64fbeb44565292795c31af922d73564e76247bb4623bb265398d8adfab10c77ae94c27be340ad481a088d89e06b80ec00dc37a01b0e5d332ec6d872cdf155cf1cef8ebff20dfbe10f2ad7d23f0cb4e08fb249d11f56d57a29d0f24d5c75db90986f3257085e9eaaa3d251c42d867c0d9574cb3d83026f0aa451f6ecec22961820bcc307398f0822534991b29a21511904380e8446715f92e90ec0fbf8f136520437de91c81489e7995ea16ef2ce076ff4677f7474cbc30eddd158731814332edf99701d38720176481117a5c9e17e56ae9f37f9d6894a8bdd2a7dba1f367663824064732cacca5f1d48b9411b293fd2feb85d6402a8e3083ec7f6d3a255bf78791ecdde2ffb9f413d3a8afae3e328dfa4232401a15adc8fe1f27665c6d44448c7680d38089af4e329dec8f322406516438040544b201321cd244161925c5552ec426fbec302be0b87256c6fa701c038ea01c4ae92a24f337baae34ec7eb815cd3c5b37331d1d4c0cd80b4b95ebbc64dce4382fc440bf768ee3a6f93424e35a176265bfdd17a2c91e9ac95e7facfce76c67f50604d6c2d1ac011843933938c68623e64f4c7bfe31b43060eb9f1827e59a859c083d71394de6d490cc27e67e623e31ac1a7c59357f5d71e64f8ca7e28a8581016b3e7edcd7de3fbe4aa52a418b5f1564bf2b683a014cb9aa4e150bb26f1afc00e994eda09b6ae704edcd052b52472fc802b72c7b4c0af80bc97c623c55bb1a9209c9c47cfe05fcd5557e1d72e5aaf6dc571aa6c2bc803598ec249acc0293dc1c649659e04fcc2766722819eb42fcd97df60640c35c58ac624784f4b025f077a3c7487b1e3d2fb8e21f371f3c2e37f977d7477b1725cfceb9809df589b9264d6681b78041395ac05fad55a3f33ffcd5d5fcea0c0d7daf36d9692782b95e1fdc2a763fee0a0b3c3fe69ce92c67354a485d4d953c65e6cff99886a76aaaaedae43f5f6573993e3a55596d8a5ff323bbbfadd7a4c52c70bc3204a09d342c0bb8b63c550a42ceaf6f65575b93f3557bee29c0dff5982884fcdac5d5c7bffb036673f1e1aeb080e77f2199904cf68fabb8da21874cbbbbba027fce7ab7ab9855e5aea70559e88d0f837bd1e1a00280941c02e009e014036a9be78349523c2659472da6a00a9793e101b4820d41a09b60cbc0384bb461ffeb2c2b6559942c69237f78d209092367248d1492fb335b4f320bbc1d017f7225559954b5d758aea48f46d597914058def9ca78aa1aa93b32f5884cb616bb7690b90a97d528219d8a5f4390eb434f3ebd43da648938cb537748d31b2ad8a6b566f962ed9cb4d6979b4bf695fba4f6b712617f87cdf51daedc5be7bd5af7f1b89d54c997ea92ab4863fc33a2e10a6c69b962776fecf711935ad5b452553d4b89a1007f60aa63292e064510f2b1971cf695a3807cac2bc252ec06b7c407d0b75d8edac1d812614b94314745ff526e881de6f7eff0d941c676283d1f8f0c3fc2cf3c62ac40bb9cd496c1052e68c19c744a501581a494128431c612846d3481690fe4a33d7fd04713181067b26acf473a70c53fab467d239dec3f42c14968411264e4a089f963fe40428c4d8c0d15f307154a5042102c29b600cb38e78495521aad6dc24e312d66694cbfac6dc24e312d66b1c876a09ad5b7d4181d93994ebfd5da2cdbec9c73d65afd6edd201b6b2de80654d3de74b7989d72522e08f610cbead63eb6b9d82448ac6298c46cb69ca5b37239b4448e66ca05f19f99a775e3297cd36ae5e62277238fa82152a7512f9d0ad548223bd96b6411d9922f992377240eea23a530e05bcda36556c5852a1f7418737f4a7f031a05531246e5fb974993825c6b8010217f7048ee8e50b628f7cba03d788b90698f32462d5ca8f2bd88351cc6961efa1c44956c6f3a6d92ff69252f6ce4236f3b6db56fd3b15ac92b258f808c7e64d9e1fa1ac164f9242e4fcd6ed3e9485cb508e7b973c605995f6709e7922fe5c32ec3b0c75e70cd1ee3ec5f68e157ae16694fc2ec396b244bacabaebe54672b39925fa088bfe9348a2bc9e9036027c08c80bf9257c92bda681264f925399b0e49cd276170e0ca77d21a227691ab7595bcb04b6f912c3f73b527df63f01ca9b21cad6cc54ad290e597f85092024c93e5a6a3431283bf92d7a6d35cc90c8910feb32b794998ec05386a2a4dd59e34d29e7c4db5ed34aa24a7bd92571bb0f554cc5e7ea700c74da7e45562a453598b7c9be5eb6a792abefc8b0359b0977faf802c594b5e9d2cbfdabf5d6fe502c39bce6fac8ac455ff2371d59a1920cbc70a90e5dbea92f26aee0292935696af72c1ffacca5eab925f234b5a0990e57d77018e197a2afe777293e55f217f5b091ab2fc92176449c9f22bc9c9b264eb22cb3fa1812cfdf2ed0b30fcafe415e1caf4f6c69c40e3854c74928d7f8f421ffe7cd86da0b6724cc883c668822b1faa7c59ce16b8358246024377fa55a604387eebe02ccc39472e54f930980c3166054c844451c9f2b117ac437b2958d6023c572e3f1c5570650938e6e9aab900065c2e57026e4096a9045c912f3fc3d45c229ae4cb93fccd15a9bb6f3691e57f2439765f96610d96bf942c577045d6684f7e5cd996d4a13de97395e597dca7fce943fe644d9b4e95d0c89f42b29c4e64396166b29453c88cc9f2bda3aa519f0e59be9409c8f2a5153eb29442ea50e36162db20f083028d6468051b8a6419195ae10620b96e01ab0e6491f1ed61c34c4e0d5e30703181a3446e4cc67b6e3c25adc59844fa77956a33b1244bb2244bb2244bb2e43b0c64f13e5a8b3189f49f33e7370e6409c0c7199ef74f22cdd039436778de3f89e472b50c64c9e1e3c7176401c0c7181b63636c8c8db13196c6d8199ef7df82ad56cb4d0d59543e3e08204bcac755b6ca56d92a5b65ab6ce57dcdadf91b9005e563e9e35f1277f21e87c30780eb3e078e7b00709ff2e2afdd02a7c42c599eba534053bfb553b0e0142c38050b4ec19a22b7ccf1d4d5f1341a9a199a199a199a199a19ede5a6f6d4f6d6624c22fd7b1b8e6786e7fd934818b7acc59844faf73c333cef9f44b2166312e91f05e52144f9fbc203d32d3238933771304b554989aa4455a22a5195a84a5892255992255992e571779523733c32c72373b2d6cc9c99337366cecc99fe1ca66bbaa66bbaa66bbaa62bf703402585c6d0181a4363680c8da131b4455bb4455bb4d58f525775555775556b6a4dada935b5a6d6e030856db93a1ecfd5f15c1dcfd5f15c1dcfd5f15c9dacbb3ab545a3d168341a8d46a3d168328e33a1a12dda0b6b2feda5bdb4d77398ebb119ed355b3619ef9f31c3f3fe49248c6370260f83b33970a56564cb8603da70401b0e68c3016d38a00d07b4e164181b8e7dc159165ce93fe1bcc503e3b911fd0cef4938040367ccf0bc7f12096391c77a52ba20a42f719e1bed47a46f1277bd4d3a900a703ff6c129e0163f18c357bffa559ddc588e700ab845fc418e63c85d83afaf6022dbfc7d5419e250e22d55a400c32e7eb44ec936c5ee545aca647f29e3292fc56e7eed8a98d9d72f8276a5389f478b5f004a774cdf65472b479a241a90e507b8e2ef4f009802620c34bc30058458c8fe1f024e721e82022532842b2cc0a7f6a6cdf02f6c657f1f5cc66cad7e1f828019240399f00222fe419c2fbec88ea768058c92a69b623858a53df836091c7741eb5fbdfb7648d822ddd52927e2de2e63b703ab5c7b2795c0382aeeeed81530ed6467af00dbc3304529fb176659966559f637bcdd65037295bbcb91bde86fc689449f7d73d9c76d871b3f37f7b5bf1f1f5e60fcc3e88c802208ed61bc11b72bf9df8ff131de08ad2b7957fa21c6df172246775f0818afbdf6301e46e7f9be362eb7af15f0a7c6a46452322999944c2a0bd7784afb393d17e6bbcf7360505050b66ddb3c1e0f0a07db1b75b03dd0c3780d46af727d99dc977dd1dcb6ffc8cd2548fdee3eb9ca5ee4a5056e0b43bb306e82302ac8c516391fc6c0e0608bc6b9cbb123782bfd00e3b50f02c6f65a1784bbdcb43d7453f6b171f9dcd4c095f9981618c35e72ce7d5285ad01fb7bde43f21807facf0dcaefb0f984f4f33f368d4a99ffa9297dc97fa680364aef29d12787c4a17c7334bf40f9fe943fe13e5051505250b6dea6b6fdfdede72633e904a5f3d776ff3a0ae7af1729db5f99b27d69db82687fa23d49dbfe6edb8f466fc27d3cb2090ea606ecbf7df6d88fbe479f8d423f72c1db5b2af27c5108a4d9d47dd75ae3b436c5cb4396d5d7277a552355c7aebefaaaaffac2b4c03bdf7ddd570f37d96be5ee3aebbab12be0ef938369816981bb3bba0163ededed5d5ff2bf94f666f6dbd757a33c3fb3ee9339ed65d78812f8fb3c899099486eee8bdc7c9546f9cfa771237badbbd70ebe391af7b9dc4d7eb5c7048ed3e727a751471a95fd7cac6a54f7cfc7308d2acd9c3cf12acfcf38d89cfcb41cfff3ae73f1b7dd2918ca2139a27950d939e15e8fc110c69d1c5317aa7c285454f1426a51e18423af518d54bd00868a2aa488ed697d22111d1540dfd38242fe464a68795af06db401e77ce5d14d8f6adcd42eb8e23f62356a8e5ea3239dc27246363f5637232223d60867e41a1919c506ddb41af565ae21443a1019e22b7e28f903bde2078aa01764e907bdb29ad865355857d383fc75af112bce284234f9a380b2fc8d58a0970c9d0e25c3cfa24ad2bfd13573652e0cbaf1d4bd2ac7acfdac6084ee99dde7a5f3e0b869c41262e252018e10143b1232320264f11f1101da00d1c419ce0209812cfd209a3862815e70c5084cb4011a039c012a035ce9fc5598ba021b1526cef0876f214b165866598c93f31469cf3d38edc59b0f0d0baeeaaaae8fd10f200a8f6820cb4585465164528804f007c97f5e0e2991fd412f4f51c822df1f74a4415b4016fca198ec2035647f101aa08df98176b23fa80dd146f6fe02bde1a6a64310e5547c464f801e6e740357fcb351157106be029ab2f7772a3c67dd874282ece942f6c7530557fc3a15a39cec55c4d1147006e6464e802ba32110ae8c58d0fb464fc83e920234f99f6174c52bbb14208a0ae839bcaa8e99cb4dad6ae9815bb487a246d93f812cd9c317193e09b4311f86327c9468433e9499cb53d195b93c9e9b2094d442bf724156355aa8a7e52910cd671d44e3a9acc64db1a321d2de8d9b7c483480bfcb1115b2ffe8721fb002663555dc8ca6c8feaeec063a740f165b620bdc7688fdbdddedb5971c113b7056e3a90a593eeb2d7f023480bfc6b913e001a20057fca57fbcb13080289090f662200bbc4902f4fc3f1090fc815e1e2c3c57401b209b38c3dfe9fb7b70200bcc9e9dfc517d5e4037a01bd08d9b3c20266421fbfb8dec813f4fcb6fe2cbdba12401e54548a35048003d87c959f78d728a8c8cbc462c6e6433aab9b189364653c019fe3e7265d0cd88d5ca232a404ce0403e802bfef14b737a5a9e25a8e095fd3f1f1f9d9a2acf126c5aa097e7f3e0a8808b4c553040f2f779f1c8386281721af5817c0032d2a82884ec43f2073a32f20164e9f7ff401614189fa7252e5489bdf2ee9577bd6a2f09f893aa4ec57eaba3ca213b94305ddce83870c56da604864c98b830ed98744c5cb8cb50c950651934261d192a192a37e04cc75d1726772942ff20e4fbbd1d8f965a6592c0fe32d3796914fcce76aeca56147522f3e31129a535ceaff36f787ea206a1a71ce9efe6121aa2f3a7055724ab3d1912d21ea605a67fc39dd3e12ff757f62e472866d7e1e166da99b828b1fc462d70d6037f9f96fdaf54ab8dacd485bd48a66ff2930bd534ea0bd974a19af6e47c8cf4210e6651a926cb2742e64fab51ac46e1975f484896a19a3c7afc5fc826cb27b990eca59cf3a0feaa3fb23f39ccbdc3258fbf721f8f3c1afd95f4646e2ef8492e277fbb37179477f13cc679fe8a384aff435f34e783e88be87fa8c9ab51a22f89c0e7e90c3dc9cfeedbdebbd999bc72ccf77b69f7d19f386217b676f4ed7cfc0e083d2681f9f64b4f7f722626ef4f22cdb7ef5c09fbfafe240eebead79f4ffaeaa73420e6d0df68930e5405f64e87bf4ab3cb117a4c87bff20ce197db03463f1f96743b3c7f1ecaadeb2d02a2ffd05a27b53f3dd3087cf6eb7722ea74d257a344ef79d253d1fbcbc425facfc46552c4337aec6f243de53c6fc27d45c478fea254db75d0e42d177a94da791effec221033a9cbe1798c078f0924fd8da60f374afdd5aa1ca80a5ceba7037fca5b12a9cb411f1b3d461f2b2226f493fb4cba1d9e75282063ffe2afd4481cf661a449e957eba1ffe22d06029afce1a7dda7c35f373ad47d3c485ccc1e8c1bbd7332bfe0be1d37197f0a7e1397a7648b7c9397684341b1d906c9de6e4156df927571e3a1248fb05cd1e0d17f72d5a32711fdc72681b3bfa199d013f6e587a26894c9e3ffb43e1f9c6b1f23d15a6bfd6274ec27f6379c6482e1ff34d5a7f521c27d70647b26262556a364e8e3f1881e14496eced581f09331314b21edd904c99ee4fb6091e57f3c8ee326f9d6624c22fd773159ca973eb6fbdbcdf67573d9e4b7eb05f7db1d9cfda5a1195922d23271fd80b598b8dc243fad6ce2ca52537d5a9ed25ed3ba4f2b2b01eec7feb3404aae9897329eca5e8632ea4fbbcf7f88b427fdd3caf26f78a9e46ad117f59d46f51379914e8405c670390fea42f4e04295afd6af385d69aa1029a5e334ea16719cf6b0684fca5c88c25a2609d13967f6754e2a67fd7a7e46bb1d9d319afdcd7e6af3b5195fcaee8bb3931db6e1f09c7aacb29f5fb9cc5d2776d8cb18a3ac9f11397ecdf24f3f302ec7fd237294f93bf9c02af6179f7a6c587cb8f580bbafbfa65f77e2c7ee62d8534abb52fdf9451ee4c78f7fa2f16937b3ff4eab6cc341f2b1cb11ff3e966597fd7c4bbb2fd63933926cdb5cb48b550cfb18f3cdbaf818777ac1db7b6a7deaa957476e473a4269bb1d58ce41ff52ec765de9fef6f53f4772ffd71d5896ffedc0b4af1b0ef9393cddf674eb41cbf23def895f65fc4dfb93f69ecd459bf9468ee64b5f324c75ea116dc41c5f7b22b9bf6b8b3a9d9d5c0396ffb94efd78eae1b15dc777da538572442e706c092e2a158be5323383f112e20eb0d280e469d87e0d1d2c0d4bf2349cf26790d101cf5a7bb8b9ca5ab3239fbfd9e6f2a9f553b38a4928a862925a6bc52807e24830cc3e5d963de8a422792949de7e3bb08c9fa4abb83bf58833eacb0d077efaf7a43af5c052c2b4e7f207889331b03dece77ff20559e4d38ca52421b124724218dff368688df3ec63903e861c4fbd707063925f913f9cfdb3938fd32ad71e71463f3d9d5e4eaa46f538adeae6522907a50e3eade2266570ccc2a082d68c25e1302e6e3d60a0ecc34137f57073d6913428bad7ee8b39e64fdb360cf411f496e4ada72e09c903b24cd26d38489efe8d19db5c624e7b7e0473ae43dab87e8dc3ed79379f8c17ef26cb506513177146d474e24b9865c8c8062c4325e1165faaae53293cc6d53339aca84a027fd87a9a28fd50e503015b5e92a81d859fc4c41165dc70b4ed0d8763df7048bfe20ab9e1f8c09f1b0eea389de3c0154c0d37fa08c9a3db5b3069c7e82de8312ee3332c77d917ee9c5779ab1a0e9303a1c5ad8f38aef852d9158621c5bc8c3713136968e87839ff22b9304ecb62d2d75865bf01bddcc9598fa9515d3dd33087f68cc79919735a46976445d58cf1a882371f7cc11f5e4deef3554b74cee386db7f1b3e0e986157eacf111f7e77ddfdc46e779752ca39e70462524a29a51b10b4d65a6b05a2b6c8bf1f8ff11897ab677a262787c58a2a7803620263206c8bfc8bf57b774164e7dde1f0ae4b3ce4ae6d13384b01036edbd0daa29bc7a64df1e983aac0f36b4d576bae4b15e01a7ff9b5d5a8a63459569a28e85b4ff5d3c78e440b7d1a9ef21b5d67200b75cd6a836b4d7b354b018effd59a2b33857ea8f2c9569610c32f50d0afd1a89b3e404d7bb5ab2d6bd4f094b5d84931dadc248054d30790377d00e906a983a1bc694fbeac913530c3968daa2fe9cbb669937cafd901fe4859926aba261321edcf59251a7464026a74740fb636426f0fd4a4edff6a64e93f9f529b65ebb2c195fbb12db0e69af6ee3197909c7a9c54a797d36ace79eab173529d5edce793903829c465af651ffad34bb40173e8b46a54e8b3f713eba43af5d839f5d839a94e3dfc331f388774d99d7a48795af9ead4436e2eeeee5ebd76d8dd3d53028b76fce489f6fa84a6bd3ed9d9d9d9d9d9d9d9014923ed75dc644e7b6d5f270f77d6307d8a1c9fcc4c891dc772a60416913898435cf625dc27ca10268a09039a3051cc1f31324eccd0b084d8dc0c2192fb357c529d7ac0d32a639ca6c1f62e8a3e6dc2fab076f425d749e954be63ef73ce9393eed3213169d2992fc3fd31938e898b4bb992975cf6222e8326d19b76a20d984532548d127df69326df2b7be3e166bfae793725adf992ca2bff46977c66029cc37fe692ef8f328dca5a862a67dfd90f208dea926f13177146e69b4b0949094e4949abeb9b6881bf129216ce3d99f114b611391971db7f5bab64c64d9fff4e88c00f49eb84485c4598b8dabe85a901efd05ed26a6fcee91393b4daebc7dce9fb4f8c761b4e7b116e0efa8fa475e2aeed4b5a8d9a93a464c653f53bf4799256a3ee7f2744727fa56f29f6f462dd8643a43376058cffdb5ab0a37b825421baa5feaa848359c4b98b84fb261049d225ad09a451f3e58e4a4e1f1326b77f3346a65ffe379f9834330a3985e4d64c3a262ea20d98b36f19aa4c5f723247edb50e664b390d629014587e8661591744ed78b4c8f7060d017fb0d5de10f0e775c087207cf8609197bf7c98bda849d40b5786386c47348f394f5dd068b274176152b880a768b829f3927f5b4f95bc3f08eb5f040ee25384fd4f6783f8bce73d5d11d84d327b28ca9e8e869be4635ad090ef37e36e30400beccaf2a5ab3d295d9ff7fc8db69efa744640e16f44ffc7d31961dff3b4fff341f47fba2e08fbf4decd7130356077bfdb7d7ab3ee0687dd684f328046cabfe129d85dc3b51770d7592b9ddc129868657993e54bf8caf22b9df6c60e69540c42966f5b37f9b344b2c49eeaa7c91007296d136ea342d98db497e32e08138b5ca8d20373705be51b6dffdafa383e1813f8c35bfdfab3729f5cb980a280efcbf6e4e3b835dfbf5dc021f3dd8088d064a21b0ecf77c3d1855cbf5eabcdcdc5879724ea27e1f6314fec7cc0fe7e62ce1e7b0a641d745307dd44818add688c739c88a373dbc1a738e0cfe9ae2e649f39b8d90aa0ca672366052ced0b26b5e77f6336c053a588fdec8c988f7dd619014510f331ed8dc01eb6dc872d1eeddfb8b7767132dbddc89bee9bfc82b5f4f8162822146dbb6d77105e7207c189dcb6bb6549b6fc9643e08abf7c025cf16fc9f94316e9040ea664155dc82e0920a790fd3f938633bc4969cfdf4679236ff28da720a903b0511f97a505288512da935767b552e5df31f74a3f561ac4767573f13ab1ac45f05acfa45a0b2e54f99a067612629a860537ae443fb914808c1c4d9656afda00582c072c03407655ae8683b6759b87939ecf439618d22425c6243048402f40a194106429894a504a462723139209c98474323a41294129894a29a19417a017304860c4c031fef39c47b3d6a134d2e1a0e1a0725500900120072c8700d80078d53351938c2943005200273fadf4ca00340859e200b49501ac78e693b8c83415edbba5bba40ee93bb5d67e1add502a355c347020ac41236b51dc68a8490b3dcd4ae869ef5b043c7bb422b6fbae32dfd3bcf7ff5ee5d2a0d15eff0d47794fa965d9897468138d39024dd289d560426fcaf9708e40ce46c2a422925ea0e805514c794e447d29399eead52af74ab3dfab1c2c5d352425a54b7684767f6276b74bbac1ad0379c3799bf3a59c31464b8a258855be852bb6a373ce49ab945175e01544032f15fdb9b9d49f0f218bc59cc216c46968d33209f804a052b50e404caa9809b482f840ab052223133d5bd77dd126a6765f248269a78aa90d6bf07b188605f9bfe1a60e52a3868d7cbbb9ccb7180b0dfb91e87f35431b511567f47f13732cd95126b2a22ada88448033fa89e47e1b87e436025c69ef222b1382e3a4f3a3eb08c9a3ba8809777257c2d89ed80100aec81c289039e801a0a1934e300e7af23f15181fe0d9b92c2df0117a124a355ca8e21c14385aca2db6c80f40883f5207822ba10d64cfa009c48186a6997d0076b3a7cb60a711933223781170fc4b21842bf365cba822310087fcd8799c2fb91b936209a801b17c2b33d8c91dedb50e72a34103ab60c0a9cc8036b928e5839be4dbeed341cace3580bb41048c83013e78aa03f6b3b8a59032a081f6fa022aaeff1b0c6894fca98344270748599eece6b5d7ef65778a30d6a466ad8c9ba73be0d22f0cb707e4f9997e7b80a369d0888e233ac62d658ae3701c1f20600b0e9863b6458cf10a17aa7c1e04c3771717f217638cd65d1ee8d8312a206365526443c88490459105210342f603ad44a3653ee801cea07802f32024ca7610121109b574804b4624da0cce82e01873403a41d9200e70e684bc2934bb416683ac063238461acc007b1a0d510d086b54648081e01834a132850b1bd51de14ac4b94d7247b842caed477822fbf71186648faee506e56eaed4a5ee44b96a6eb5e678746c22dc24a690441692284316ae4ae749ed2886cdae7b491f38623fdc80882d1834f56318c949865663c2043b9ee11013e8384e36c1cb0a2e9e2041196ab27f94a16a6f9e810777736f96651986fdbddbdfc7b09a31ed62d87f300c377671b20e7b8cfb74dc7b7feb4c3b714614acec97a63dff0f7765dce4efb9b97eb96eb3ef011e59bbdcd586f04c3d6b7fa337ee3b225bed1a017f7e86afde64f7334016d81956ea57d3b4efbff7af898b38a33ec67da69d5cff865bf9b7e6761d03b63005512eca37ba023530722557a7d53ca94e2ff3b4c24eab0e5485547df56d76605906ff9398bf9f7a9c7aa8e1ee10bb004981e3c328db2de6a6bbe3c01e526098cb19a390538fd3cb49755a9d56f9c43aa94eabeef3447b4df399c9eebd7eb3d06d699aa6698f72432d9356eefbe13cbf8359cc6216b3285fa8c5559d175c9f7e5a6eea50ebfbb426c9778ba40bb5dcd49f9500875a19ffe6f9c6dde73b9e10ce7f3e9e2e149f08a9ddd6d7c2c142bea3126ae5f64e26ad4f532958f0d2c906c870c80a6cf28ddc875bb3b1638e218ac8fd300fe1b95164a8e017bb1d9d65a8a246e2f9eebefa58ff77dfed7b38af95adf62428201b1d8e8371d77936ed310e5405beddc72347b6434a7fb71dadb2bb92fec86090c12083814ac562cdcc6430c8c98931fa200536a29fbf8228f201321cc2c44ebeefb1ed6157862a4f3aa3b63d20db705813173238283b2fd25ef6d6f3d7b5eddeaa699a562189a6ddaff5bb2420ed6f48f4b213755f5fed6a577638cba7f333f9747e327ce408fd115972bdf1e059cbe65f19aa49b52e47877e66b283f6ca4fde2e47fdd0cbcf5e7659280b55793da008843a1d8ea33dfd8c87f9b287f9f2cabf9d9478c3210afd67eb418b1e8ffcec13d18cbe67c3313fc7edbeb8cd9d6cca176175d2acc9ac85aafd8c9bdb9370d9dfcf470e9b743c5c9dc9eea9d4d3dd9fdded240ac8a67639a616a586723f6e11d02ef7e9c85e663bf4e5a3dcff76c8acbd27eb4055601d8e932ff6f826cbfb39b4fb9aff76dfa463e1df59e79c53421317de8da7e24faf957fca961ca1005a0bdd87db1b10567b1e3a7f21b85b0f9e3f11645b0f327f23c0b61e66fe8ab046d4ad879abf23e8d683cd1f8ff937f3e4f07cd6611aa765e28b06eacc0f1261d65d5ca8f26930d9776832b4820d450890a1156ed8c9520998b2302e5736092cd60f6874305303191864b7314c64ff0b2d0c9c31c3f3fe2d0c74d8622d27413df07771703ce52d37f95b8b3189f4ef79ad8b936b2c8ca7ec5b50122d0b7345f6ef120f5de4d97d43c42efc463e8804f2e74f98e52a89d5845de4aff4809923dfe8d203648ed9f90d5cd160681a543e1360218c3dc8ffe20491007fa19becaa8c55590bd403c3c0c0c0c0c0c078703cf5b1166312e9dff33e309f1b5012d8fffbc064f71656796abec74d85a34895210e72da0007ac41014d26d5a0e00799d4de9433f041331c3283971c718632382283d71019e0e499e110194821f76b8d9a32b0c9240e073ae04a93db435d46c8721f62b0d6fffc0b193e949fa7546e0d80d2dde5da689e518b76461be59c3fedd7faf3dd25abcc982ce2aef6a4a6798e9cbb863842953b5bf9557e104c8b5d90ac73579db2fb76601c742d4659a9e4fca994f24443a551314b29e58901327a27b5ece14b4a2ce6e99434e5770bae60b2d669b5586b7d39e93b279f72a69d38e3863b9d4ead906288bbf4f834d549ba88e1caf2b11ece51ba7214601e99fe17729578981f6992667dd24b7bce915eb27cd28bbbbbbbbb090dcd98789c9342b9cab4e3912fe54a3cd04f712245d59ea4fe29292fed490c077f292f9e535e6868c64db27e29a774e44b51ad2af65f4a4a4c0a10d07f294e64a961918bda8b9f221fc7241f7a354a3eca47f2d8395c6bc53893871ba56edd293df538ad6ef8e4e8631cfe789c54f4b3cd8556131313933f99986011c47d318376e8a947c8d5271574eb033bad4214e227da0bd1b4275b44683729cd41bb104e17c2c2be2d09d95c4a35edc9984488a6c64df2718474003d4f7e042254220234c9a7984ecf7f5e6e2ea02860faa19290f64251b467d39e7c1a9a812bf2695762c1954932f92fe4ca3da9a46fc271219c50b4a4ceb60be1348a763bd42e84058eb5d8935a44c88fc9a7d52282932516593e863db6b960cea9fce3eefe913c7eff7c7660f9e4415893b6cf56da4625b4f340ac5d7602ac5525accb4ea052edc07a07b603db817d4adba864c33c1feca78a9e40aa3097ec04b876df0e8c7618696293f4b372740746318cf47912e9436fc2eda0994422612eaaec0452959d007f2050edc032e9bf1d1846e23e2a55b7dd70d01fc23f9f4fa8487bd2b504febc892b44c24955367179aa642dc6243771955c2157a808e53eadbab9e02e62acca9452da7d3bb04c09fc69652b5c72958a94725254292f29ab141faf2c4bae924e967446d147939749914fabe56a5467f99f9c4be26009f7292097bc8469d4a8fb621ebd74f76ebbb0886cdf39da39f796f3213c5b12077ab859d253192a9fb362dc7d3a9cd43ce89b744c3b32e80daf1c7d12f7b9d194beb6b950cb853ae7406fd231ed80404f7ad06f9b0b8864ad88fb62165113970e772226c0dfa7d51f57a3e6ab51b452221f2c1a55a45101aacfa8748dd476492d19d1080000003314002028140e098542b1683c228892343e14800c9aa04c76541b874912438819630c014200000000040084864902a888b26ab9efc9d34bf723edb5a6a1e6f2135e357e51f6e3854603eaaded01445cbc22c0f7d5c905b8504ec5db2de5b70b01bcf1ec7731ed6a57316f01562f5fd3d4f7dee7a045ae5ee98fdb5a1087455243d52fd898cc3e0d26117361e655c5c28f21f42052b76dc213c90453583091c82ab54494eaed41d048b2026a2010263c8ecd8b7b5d3b5a9945044b0a42d35de60ba3d08d42a23823156f8d3e854303e7b0d3f92f90e23f270d6f63f03627fe4de8840589998a4d5e0259932505f521373b6a499e8df06d5b2f88bfe1c6aede35506ca0a03d2a37690d2442532082babe9e45e6266b7bd106005df6b7f516e56d0dd224c00bfcb75e91a8cd229b31a0069106c8ecd10c940a86abe8eddc9d1743d1118bc142b97c0e20ee7498859e4ba8291e949ca3c20f995a599b473005bcc9beb6f17cd5e93d3f14bc6ff51551db8b3602e0b2bf2d5b2b6f338826015fe6bfe5ea246d16db00c0cafeb798b2c8c6e11a06f0a695fec41bc289423b2635a69b6f92685abfc841114e1ee6e2222c952e77933805e41a484eeabbf5960b6c2ed634c091dfb6b8a2a4cdc79804b0f2972daf92b25d54c30023f9baf5595da1124e3b2fed6637db9626baec318bfb849cb1c9dad62cef1d850fb6ffd877a94716899fee2a6bde851fde15403d7a029f58c5ad4db791fb3e0a47f7d0fd99b915387586d7fbd61a821e61a796fe2b0de75343cc9b232133560084e132567d09d28dc81020c2b8a62cfd16061394659c522c4c8c8ff970ccb11303198da95dccd448599bf9070a9834a22a102ae5240ff480cbf7acc8c683c2273f71ad2580f3743d8895c826c6618d1236e6e7f11682e45a5de2e8acbea07ae8144ea507f53ae838eebbd4e05fcdf887d145ac1de794fd868ca55f4ccd8cab6a2177b592feaa08afbaba8314c2a932da5c494114bdf4d3fa9b6e79bb4b4ed690fe065ed5bd9f28434a12c72dd803381d49a474dc2b6a68cba09e0e2fb6315d3c358eea7e2baaeab0f1ccad9ab8e9e91dfeb4e2d37045aae0a5748037a62a4c996c2136f0ace8f5bd787b44aacefbd79fc652765878410d305203c6221eb8602037b453736893ea3c8d9348ad572f1fedba7809107c6025ceaef1c1a8e1604a72259424471c20f15eda8ce01e4376cd12dc536d64cf048aa3d622aba020594972734b914c5b502fb0c8be56089764f5f4470a5437de7f4ce3ac1aab5d68e4f2e227c1bbe5bd78e422b0579070e84c62eb770ad9b86031423068550d4ac72478c1aa72bff479f3c27c1aeb688e788f988d0ed57eeb160bd37d620c030af51d00d8d4db9740fa3614819656fc12dd8d9070da4aed8443607d09f6059add7ba429af6b0efdcaf7329e42b502761250d5c128e668b5f84552516d8dc3adf5b518c9f5f894bbfbf6c5abd6cf366d85b9e1485813090da09b1301db8b842229cbe0e27240886eef14ded37f40e57c7cb0abdff332b78c949c6448ff638311c24737d6258d4bac1f21f864f39bf781c7c951a40bd6c96c734a5cb35acf05065188930c35f54d0518ba209eebb6c6a833cd7d8452ccdc3ccc2f598ad5e3377b3c8560224fdd5a29aec480aaaaea579e185b8d66b0531e983ace346e6967ca22351d18009564d6179743bc79bddf713598de0f44697b6920cecd26dd6bcac83caf84955fb5b4b9d0d11aa2924760d9c983ede4b01c3941ecf68e96f331c74317489431f297fdfcdfccfe6ecf3a7df5a09e30614efb67eec229850dfe7bb6ea6f7ad978809124ca60d70462ccd1ad84bd2c0a9e7f659560405005222248ddd343d31a3ecedcdf36577b371df645439ccae99ec25582ddfa842841d73628878170fe6b152321a6e7b247c9c927ea7072ba96a3a075570d06be1554b9f871981a52a58501533c83cf5f2df45ca0d18384b421042fda1a54fd864581647d3c8b2cafc3182deaeefa59ba1cffafab1406581903aaf3a7c536341486fcda660d03a5e1385b45bf600ab0958047c71b81898574f0d32c759b152f84cd50350ee7f4f51ecb1e10c20438c6ef47e1dbd1928c286a50e031e2b45d8e22c38fd932c1f20df2a12ba3477d27472d157da4dd1fd41760a2bcb7f22f9518006e3b00c0b9c24476c444d8445af3755b2501c683c74036189ce50afa535c5cd0a6510f4e99bb191820f1592579fe69eb7cb3a1f0d2e9cf87d6bf1a9bb2d9ef4dc9741adcd94001842485538fd1596e950963475233423141b8421246d270478a34010c8eed1853222d675fc084787190bef1261f3503d8f32a31ac0b88f901766f04d33f2bd1d79213bb3e0a164318262a6326e89779ecb365a0ff31009c829df0e8b626a2e2ec34c4ec39c8aec3b3471151ed5968a2d1226239528d915aae8cdc6890a5b9dae10cc0b8176ef6910a3c9ecb65197d185df7c616e3151840a28f210af4b0a57b86ee67e2a0284afe6084a088fdf4e692beeef7e42ec0b8ec5c8317cdfecf57cdc7f0e36ec37c630cd00f5283600b3ea301b3b0fc8e576759240e1420e92a482e0f2f42a932c170e2341b3f566bc73537833d090dfecd4b451ddb012b06991a77c9ab811ba5d387818f155f6bf86bf12c04d03341199efa4c47126b91c831a8b6a42e6a891b3084610f8658b89c3bb9d811bbe86a585184f4be1eebbbe04333e887b714b5096ae655b7a32af9bb4fa9aaff7101a25be4beafd7755162c55fff4ea44326a5e76b1495b34312f801e3b4d69bf0966cef032b22c611a5d1d2fe195f6795a4e48c2c6a98a3b8fda30783178e393fbbc2c5fd00c6078d3dd861f393e1e4b4214a2ff508ea3a8ab8010a32359462748695e33f56cda586f4844094990481e8bd5e009015294ea82f4cf812000aa9ff988a3c303ddd566563067df8e90aea47edb86dc310089782d0baa597119deaa0fc7443227e3451b87f1207833a227a1480b2e1982e15b411a587cf282de2c6ade34bdfa7cffb739ff1d80cbf67639c1537dc3227f63f61091175af8eb5f58ff08fe7ea00797c37b53ff1a9aee64cd0f4ee4e35fd551d4e7dd020f9e865c4854233577ad205e2f92c99ab849264a92bfdc5e6703eccaf4c2318b6bdf56fba61e36781372c12a4cf1bd67f88ec803c41507a1e073c3499e85bb52dca846adbb3136ea231a3d59ef697edc14145c8abe80f1d64281ae73e57a5f6ff93b42477bcce7de80a9b46d10b6148a3a56aa9bc70d38867c554c24af9a14467e4c922d76848d6799893c52351df2d5a54daa40104385a420539adf326ade58ea0fd168016199c21249d9f1de2f36d2d17a3a3fd978be27b3747db84b96815391e561448e78c8dab2845629a0f0d68cf9fb3365d82474f329a5fe69e692281317db2d25388ae5ecb08b346b4d283bb2a78e45d0cb8cd8b205e33e0419b0168ad888b193807a6aaf6b944245f283dd49555e7c757c210f9f9517373ef06fc8f35bb51f73bfdbdf322db65b53ec154aba317fe1c417ef6efc90cfc375d9ac8bc41af03f9ef89dc4ab829e16555fcef1dfddeeacd281b304454357586e885a49bad798b3aba24503f93beaaad79c39d7a741b1b3ae565560be07bfaf91b6aac58ca178366868e94874148c49298d262a682e0057c241af0252813c2f745e504be2fd64c80be78e2858c266c88b5c0a74daaf4d7c51e3b1c0a265ed2b647d7c1bb31362db87abbbb51e3c623f8ee9e8f371ac039e4263a373a7f5d09beddd8045fa60885bbd2474c9b50a3d8e06806f3c43391156f0079d586824f3dc9686762eff5e75edf29f85cdf2685587525fa5686c20a3e52dbb686c1051e14e26c97259aa57d40e16c2bc6d73944a52f862b0a389bd611a949b610e4230cd31fb5a0003e0a0de2d4b26c9a7e8f2acf288a53de72cc5cf5a65844e23d47bc797fef011b5769c629c1d17aa33ee0d4cb746b9bb8589734452cb5869aad567e944a1d6bdd4e8d7302923023498f5e359d054f19828004cd5afe852730a029c924e6d002882841f916d694071817774c868a82b472ad4684da8dcb39c858fff11c3ae6e1ceed5a9f8b66aeafa047ca03cbef7154e2daf708c7e1799865fcd6b8e4e0d9204a13d0ad839721c9775469a45a0b8bfa7f9a7a14a3592813ea82249c29348181531d60c0951960ccb5082eeb82d0ce432f1f8bcfe4aedc1d1a844c2caf647f71bc016d6070e9527bac7fd0106830527c5ab92248e220acb077990e2a1423779e98af875e2ce463c7b5944b9ff080a60e73756b637ac1954eb75eb5a40d4aa39f1464b4263e76eaa0d03dcd5b69dd3056a50a476361ea9d4948ca4c14dcd17d231b9f2eef5534885d811393710851970b4ebfa5266d376bf72ad6c2a6403b9c9771860ed6dc6eb2ec52052e5653611c9fb099a61cee3ff6d6c7f9f634a840bd123257bdb849ba883f9f2661b3b81587d4008abaf6ba657c9eb4b7b77e020a6f554dbacdcf6e043fe6c759970598e841098a3d6ce9ae4dcf4c64886224de07708a01f6cbb10d447bed3f610edd85088a172885610f4ba0e3998cf1618cc859a414e7851363f8e2a0f8dc8e28151ada1c7a006b72fb6d6f14fb624de01a922ca8403489281f8c9aa592371a1e413351804547b20db93a650022392e903126a9eaec70f434ef9d909718890ccdc017eb15449c4c6ba9826bcff0386443fa52b99748d576a1513ae43a56431a31d6d8a96e00da1332c8c45220433843e230610839bb2c399a8cf35db29cbf928f504089d14c52d4fe537344b2fe4bf770ee27633031ec727b0a4cdf8444b9f514bec848b8768b915d51e3e49a6a7a4577f602c171e10ff73eb7f58ed635321dffdc27b274c0223aaeed710a44ab534ad7828758e779989bbb852e3d70c7df9979790ceb584373075a55bac171b6650e370efcf62064ae03b339aad9ec62910c063d01c0ecb5066e061478f75516a9580709d2148f11efda547f7d239a142d225277f70ecc6707cc9f90bee13b404ddd056d57649f1e0163cab072fa53053a3b392c88881f81433796a11f9e899019faddfa085fb9c813dd524be8aa5212afa4de104effcefced3ee296fef58afacff577f06cf59f27080efa4083dd462c7dcbbe609f20a00378a788866702cd2621e7aeaa7f58306037fe51ee0c9b8bfe242b7fc1fc7e502ad8b118c08c81470268aeed17d835330a9f8a96c274e8efa33a396c3ee7ab2964a3d03ca4479e4d657f01ab505cf8d52ab2c27870f2034ffedfc60637bdf69e985e84322cde80ed7987546dde29dfc23af660480110fef28e721470a67b068fd43936f2c5fd3e6844f57e2c6f748775ced668ad10225a99678b0238bd427c10852f77735ba0d589d8f19e098f7bbafd11295f9ea12c411a4bb157db08f1021033e9e25f288b1e6ed3b83d00f9cae9fc29da08cf31dfe25659cac31b149f41cadcb0d266d38e06a369d5ab2e76b696901e746d63b5999b3b0fbfd348ebfac8a2009fdd63c8a007026cfbd39948ae65956a6b05774a20f37b47c1092c9d8f1ea0ce919d6fc38375b615fe9f9a562871d9072cf10c7b034f912035da534e02b8ecfcb92832fd01fa6383ee720dd537424f3483243a169c767c417e29223b623862f4e67851aa052fb31cae65d52d1d8157834ce22e6b317158618816721dca5b88315f3c41f2f987721f7ac73a85a0284ba4dc0308885e64c52451b4d3cefe2e7d2558c42ec5a7e23fada33398d881089e313aec6692ea44daa9424d8bf0f4393b035b7828f68444806d2b3c31013fdf17e6abe758f9ad4e21ce978f1a0ea9abb2756be16a185c27b37bf435e923f49a30ab38759267ffef8c639c02b90f02cffa365a309a64a371e36d6b36a9f0eb13e01c1213bf9ccab4fd8f429f2d7e099ff3af05bb48f805a8bd784fc13b20bdefcb9d2a2d0fcef977c77d95c7b90f5f0cb7926e4530fb921008e3ff421bd817d32fd75ebfeac9e0e41a790929562483a535193d0aad008bb4a8b29b1858243a1d245cfdcfdcef9fbe067a0f65c472cf2bdb6950eeff68786ab74e55e978d2837710932d2a3518dc41ccd8784cb4438fec079884af40aa1bd0f78d8e21113913b266b1ccc55ccd4f6438bc966ee49eb3a9d2c2e0593e552ca1b0f8a60333ca8bdefee00ae02d311df2ba8a10f94a1c7d2e50c3c08b346736ac1e630cfdc648c8a03de905362af2e108429b8f035aee0329518bb49127448f872a8a11cdf99ecc2a28a8c3427ac1c1af14dec376e9c0020555358621f4c6f1d2bf3cad146ccc90f3694ac12ca2942a0b66b3970acc489ef44a5023223b74bb4751ff5b5ea9b198808a0a0067014412d034ae924b8925f6357df94f9d559375627453f1295c36e4791e8cc32a48d7b2fd59a15493c67d207479403549678c3f5a900c42cd828675d24bf5e523f96fe5b586187c6a741e168ebe11af7a207d434bbcc0265ae82c665286baf0943dea1ac9cb6238c0b3ef21b204b4056070622d0fe9d736c6047d8a8ab11170dd7c1ed9311fe47102e754d2dfb629aa8a807115d0e347504f5f14bc1d5586fe1c5fc66bf7eeb3788967a347169d781158b02e0432517e38bc00c72b89cbce77044523f12c6bf122d68bb6f164e2e74efa0aacd963b85523c946ef11d26d389870de913be1b05cb27055918081f72c255be50a86d34e7ab6745d9c85d292bab33d0302544f2884a9327fa00654b6425862987c4d4ff0e382dd55e9ab50571676422673f21b3e3cba0e01ec6e5cab0554d322c0caab27f3222838758564af5ff31b221b61be0ba6062326b7dffa7f67701644073e275c0a254782796c093c419e94d079d2a78761758c8cb3deab7b4e401dae8f14fae42530f3c4c706596e664bb533e33ee2630dbcbda671a874f8ab590bdd5fa50804aa499295abce8ef580259f8deef8807c1aa5ff5eeb063fcbdc594f40a9e7db7a2790a4ddbba4a7c560f09f52ef14a491d1d070b3779be0addc95190ae268fe6317f1ae42bb9f67b568ba7b2b99de46303905df1560e9c3d71f19e0a310ebc052d52827388e54a970577c6db9b0f7c1de0fc1e6a018dd7001e31e8572dab9188df5d2d8c7387bb37a0d249af4396470dc486e2340e0c8b1bbfdfd035384d80fffc7f0d12f9b3f01c4393eb4ea50940a5f75269bd4bf2313f39f333ab347cc20092bd83842c5c961e0a5977eba0887c0ec4cc72313970d46c0fc7c37d752e4e50f847a5b8eceeecd97d7ec9444054a3da094dffcb840826b4582493296472f1ab316a7ac6cd0ba2371475fbe82b166d33a85f81b0c0037c943c2cd8a9cb47d8b71111f8a2d57713163fe67808b0e297bdc3e212baf088b1fad94eb65e20290442f9158a495257837372cdfa7a24b50de46015c569da6a9ad9c8048a137980f52c9b0bebe013363db30c9f729aee22dd7628bc920656a6189fd7ef718d01872a419cf20d0a3245df9a351a718a94c109b76259fb5de70fa5675b592030e2b403f9b26886c47d0bc26d604ccf95f8b60dd0a5daf910d812293ae0fb7c24b7a0010e595646d306a12707c329e8e60101e27354650a9325116785090c5793fb43d04ac8d8bac9d9c90d6fba52ee0ab60b2b0a882251845b66ef9874239cc8418decdf103515d28f81c7b2062255cb7337be4ea2ca2b6e2bc4f0a355ff3ad0971037cc0ee9ed0c211ea89aa336b98dbab0b56b10fbb37ac932ebd121a2b560e55060555e01b17413bcb48b3f11122527f2605dcb1f17f5375033b45e8ef657ce1f538bbbb8a997f8d0f7a73233e1efe45e4e27b0ccbc1487980730243218ee65a7be1998efb8998881373e2398bbe388cbfdbbc0f25b84ab6b2f42ff56a45575c79a0315aceb86efe909ae607c1fbc1fcc29e1aa46a08aee4f292c6d3f3d46fbac4bd0f878de872c175fbeec699889ce28d5f6bcd05695d80e21bceea4e4dcadc814e4a40d298fa2a5480086f93561bb8224a630d619fea14e682080ec4e682e0f8fda916f53315221a73edd2498ede2f1b580b0b2cebc6302f5ba98335008600940185ba669490fb1df80043f8172bc7d421f016f189510cf30c2dd16196a600a94ee5e0a3328081dd3235a16eb525bcd5590be13d14d4ba0eaae4a064c30eb30a083517f02a93c6bedce5c8626e6cefbb4a05016cab33804223ea4580d70d97de9632f95dc57f0262dd079fb9fcbbb44d5663112eb3bb0022b4b30bb0618d5743e2ae0d97b2d3f5234932e48a0a5dc14fe5fe1eaaab4aa9662419bd075f26218a0b9e761e7b4a927164fe547a7dde90fa52d29099d62b1c7389b2ff9bb725aaca053f0b6091cf43a5f024c3307d8c6b8fd1167dbfc9c6447a805ed1c4f436f186a8aeebe404da63a7b63bc9186656069843817aa336854c3c375fc0e1225a5d3124fc11e7f1a246c4be101e13c5ab916cb3d812e90bc4a2cfc6facdbe20540fd69a10ad5b54e006ea5692db2f24ca1c4f8bda7557421415dd6cf5f710c0b2fc1f8bcb99e3535d7a6270807d3db99aa0543e7f5bdb6f8c0476a640cf25e4d1c3fb19c710e94d49ae78629e34bd00a939ea26d9e444e2685f6f6f5914637434d1456c2f408716f2724c07273462daf2561913dcbfd8ce38fcd544397cc06bf8fc965964e5809652b150d7ad917984c6dabc65ba753948eb9e5417d8151538944e274ddb9e739b2a8805459a90d0192448a69e34cda81c577e0a4c58fd1075d97a04975586551db2c59be04022fc791bf681252c860b0d2f5c51de90dcb45f11088086ad8f94ab5e84d7ff163aeffa659729ca605279069bea51b675d91f4467c3329a473159b8287318bb39946166e28c0b0e4e9cc8c96a0c9862f79f6049f0b98ea609c6a0990f67886e67f3c2d9fdd27840dfbce16bf36b4d3191be9b217b56b30762351f693c85124d2c5c02bf4ca0a7f8d95c8e2fb5b6a62b5d6bf1b9a29dfbdf62c0265bd84acae4554c1dfbf7ea4f1c8170628af81643fb059f12c4071b9c64e949aca8ce0172e3ba66cf2dbd1a157da41a3537d09d0937cba9425787708f2a7bdbc7e340da477b56163a49894803b0a608122bd9d7331f374cf13a796706a16016cb5e5802e35ecfd11bcabc5fde5529da3ff35d901cd950aa521c8af8910c71259b329dc61fd79b4a4da2ad5dd546b3d1c9cf49b143d6ed8e0e9acd204981395cb88c03f3b2ce9c288373b242f437db46d3cc64a1ea73a9f6b9c4a5062cfc8f0950e35f9d64de5f82af1688d690cd56d9f82dc303820bfde3653364e41748a8f14f89087ee03466905a435d1aef3946975098dbe1fafdb0d52cece2a6d6bf8fa0e443b15069946cc60b26390459e79374e0d8ae9329f52db5c34dc9b26f20d490b29935403e6a1847ec98533617041920757244cb04e01ad8011c4efb2181d22c1f59ca6084c3784d8e3abce58052d10985207c4e35f78ea974e3383157c50deca2ad6fc1613ae7f0bc0e7ee8eb4e57d58a91f87b1849c8dac65ad667593f8c16d0312b8681926b6d7d6dc5a38bfaa4541f947a6d91dcc99a19a79861fe1d365b0f2dbb33e528455092864165a81f767cf50037a9a32fe77aa711991f0cf05c7f876ea6689b69a1fbdb4a12200dc13f378047de87e3091b198ec7c6a1df92be98b77bd4514f6f99d69f3990b0a777334e4bec3a550bdf58d9620cf6b749c324f7366f70afd94a95fd999610752c24605e86c6d01bb3807ebec318804f0b23ec7019289736c2727f260c6690f49f9f35aafe23d78cf0b872a4f96a1bd37782e01fe38fe88bc4fbec04c43fc667358492a1371acee2c6bd9a4e0bdf7d5b8ae12f351f92a09245b672ef363f0ac7e0e0f67409f683e3401d3066052fe24ba9ce93058beebfaf78c5b097ada0054ce99d61498e4fb90c7b9641a36e9f1b12a212ccd9e0f3de104056b3e9674b366acf037502314afdfadf24aeb465f707c0e85006ca33f3d4060d395b07feb2fdd24020a8a847c985e4d3f8543bcfddfb7dbefeb13417e63e3686bcba08924c8f8ed2048924b430e561357099bd3af8f7226e36619949d59168d13e083a9315cd5c04dc78a55356c86a60452004c388059a1804f291ce2cd7ec8d040b853c8425c72e4050b9ad6273da585281ec160fca2b7d53a096a4ba40ff5e751877d1727f8b0c59419d575c26d95d60af8075875e16e8c24e58178c90565e995a3106ba648c5a208b07afc1f149cd06e0a90dd8c90d0c8acc8095a3ee3db9efe11b0c4403bc502ee6d9e66225cc5357bfc16ecb83c91594de40530bcc758ea52e4f5bcbc69c113eec200d622b965643a61f004887726fde1978ff808bbae8823e70bea628d0fd4309089d74490b2aa2b31ba5168c41c7734c2640986723bf0fa3f7832d733afcf66dc8f42d78881bb3a16344662cc30eff1c081d27db8db58780f96fd1333a8276780a4ea025703a60d2ca9af3dc42ffd198808f2081a77becabad046c09e27b03c7514fea496369ab928e9d0ed4bc501dd200cdc333bcad74b709afb83e56bfba50c1aff9979ea616e09393f079178e24875505eb54a47054195942d6e1a92f7543f400b638327b38ccd225935206d57287e78ee8546e3e656e9ea086013e3ea4c8c8ca9853a5adb0069cc13159b84455a37cd93593d9b16107d22c8427ce65b418a30cbcbd48e33b3e3ba2dff033b9a3a6a4c9362d2b532af84207b28a8e41977f350ff113e37c27cdfa57e64251d133077bb493ed9daa2ebe998000d213764c8d4352a42e367ad46f407a0c23007d5826eebe4470f506c5ebb18c34d7f510d32601f7d49076b85d7d3536dea3391b761cafe9af0acd13b8429a22f56ff6b772b5b35450fe8f0e193fa47268bbbe11d7c4c594d07398af51c1ca915999ccab9daf9bdd36d8a2964f4a4d77167dafc897e165c699a7cee27a85e5921bf2ce4d0d54632999535dbc7db27e0305e1f7ecd32536f72c6a69134a7e4947bb3819894f216cb209508531b790876b334fa86251cbc27e602770e711679b18a26ea5869f2fafb5b5e505dc9c69db67d286c4a1e446af78eef98dddd5883a940c84b64887ed8fc54b3fc5cbd8073d7472b2d9a79aceab7af9bdfdb2519afaa1dfcc2fa9ed94a7d74b50aa190537b82026f02ef2b9fb18ee1eb302a8627b9e78e0851173e36f23692504ff3e7409ff9ae53624cc9d42a8fb7fbaade25a4770b7c9040901ab399bae4a35a6757c37c871853b4701b14c5f34cd69c24cb7db103d02fff11eae842f73dc19df719f41ad1e61a0894d9b9d0a9ed0ec32a8a43f910ca194cb5e9b7a74560922bae153827e18353c575375626baaf0401bb179aaf46c3af61adf1cac32a5ce1b52ffd0f59b40598473d9a5dbe30253b56f483e7afd41c2ad5a566ff16696be600d62313cef4e08c16dcda0c1087299517b4e403f66d28b3324b8ca8ab1f49d19b5bef1f7316fc4b37307f0583d3e8911239c2aa45e18da90ce3d5bba5942528f36643841f9cc057a9353b9b4217fd922d890ac4755e6a1da77c21dd8b8a64582f0478a86c28d67b2157d691cd4b71499cd3aa0d0903d40a25e3759a9893664f6897db0aaf5078e7ccafd23e827174535963dd26163a65fcc90769e58682040fe928d0bf9c497b43569fb89d80f03285d0180c6564322a369ee9c88bd55567327eeee32d7f163e3b220d19e856a24d79f14fbb14faf3ad3b4ee43060f734a860e7d6531b87e2010d7c3f06a375be6efb7d9d26346ce975489ed1a323b01794b000d3971d261ee6f6e95ffa65667b23f0f632288206c7be59f8004bb284be7980e63cb19060db96b5127b59b8d23e3c226047925955c74c038a443aa737b43c6952580a990ae26eb4420695e6c4f4716d281cbab622b5d0d1a121a6dd5f3a021b37b407b68c304edecf2c1c027976b2154d5d6d820ae6819b19af06ac599178ae25e05d05af4ec49650fb4aa9a8ad3eaec6a760b54d61234632a39e804d25383df0e1287f3a021e3550aef409238c03ccae04e40ce5dba89a8350bc6c9bd713bb2144af607f4b17aafa85f06171bad74ff80863c66f068c49cfc6f952de4e955be59868d21763b1c4b4f428619b21539954d388c8ab693a08b41ebd05eda9d9669cf1f5d1833a4fba58928d62c142890d57d77114ce138f3bbac6555bcbffc49f392d92c897ebb1f3fa131cd35ffaa232378914d89954bff9f3096ef0edab6e1b74fc3e678877c2d80d146adb449219600d044e02e25331b80622e310a711ac7024e5b8e4077e11036944efa76e5b54f809b578de28b9f413b99f69b6a7ad64bb4163ed086085611534c725c0be8c1377904d8c35cd80abaaff74e73cffc4d5f14c0521b360375e4724f6ff01e8b5d9cb580cf9c48445f4b2da22265a3b899c89c1a6ba94850b313ddea7410e3c3c94b2ec4f511abf58f5a699d6782b9b39cd2243a68c4d19487444cef12ac3cd1433cc46f4e0d01038d6a0670a3334cfee5281c6af543ed5d78e1674b1eaf073a7a65cad2939df6f1fb812eac0513746b9ea35459d6b19bd172f680cf86a385b9d9534ce01343987bf6945fa2cd2326f93932ad992cb0d380a9ff98a29ea6203a7db29ea7ec1a0a7a990cf055fe4839ef75185280d4691ac9a5ad28bdd23e15421f2f30404c46f89cf887bcf14aae3fcae1406569bd19144034d7712a9eb2eaa5d844fbdc58a23a90414c18c219a210200885a04ad966d5beacfbc2280b4f0225d650f03b02c2abdc273209d6d183b7373e2b4024e9708d7abc0cf32ab6791571a433fb8e50f524e0f29e51af201a7370794708d41d8a080b48a447ee08d7ed78673ffacbe2925107b1916ab74937dc0f1cf4f945b4caa94207256c21a2ffb0fc87157d43488dc393dbbe320ead1960c4a8d0b2784e892472b254bbf078e278eea6a031e20556fe615321ba268bd59bfbeb0c8011f8f61d31a22f58c81d566f063f41daccf409a814a6a7d6fcd597423d22f2710710e8128faff568b4e44d24398948bd8142d1c25e83e2d97a43522b914939c6711635544417929e0296bc5fa8529c569a76562d2af2ea212591937f8955aa7846774841762017c7e93076573cc210cc598920caabc1e3cc2d20318c7ed52c59b213980cf9716ace8ae28b5b290a270b83a0523edb5324d4f1ff4eafbd20c1d02ead83d80fa27c1184f330501e8eb6e60715ac16bf2ace4180d9bdc4fd38beba370960ddb9e1b174324a723fb08d3b92987ef3e479269dd97257ae50cc76b780c4ac528d7a4a301254003590e3b7b7304a2631a582010322ff74caa2f484576017217767048c9aed2a8806ea4f2bf2bb343989a5cdc7915a15678f188b699e1448bce5eeccdb471f461c7a64cfd1d762b3fc0e0a2a4465a0636bd5bcdc9dd5b7b99b3c7464464e221b918dbbb38bfe7ccc76207fbc2e93ca3dba40befc76ac0b99ace242c6c2ff914de27d1facb59da70d4d4313075b590daef329a0e1138d50d70fdeb56061ab15b2b5441f40d79b7bcba8e01f1c4c216fe6e27cb2c3f9e1924b8111817a2631fd202bb18227b6434142561e0fd46cbd4d8c29c871c78e4020229f8509aaa0726559b9b71aa9836deefa1261d48367ba1d43b4aee375a7179a7118dbb29520d3076583288d1a8a0d845869980421d4766bdcc9e07fdbfcee49175912d0089162ccc4426a8508358ac4b3db85405f2fbc88b0390e3eb5dad18638b7fb889ab451ce2f36c0526ab166a5c87b77512f4281b7b2eda06b3274e9ddee79eafd122d25d0069195a810c32903d37ad9420c281be4b489c8110997009aaa5b04453406099575349f8a31326ea608efa60c6f2611d1a23137a279ee01777136f1250609ba4fa60fa431be9bf86a2d5d517a6c5a1f1e094482861d257c0d9cdeb8a89ba785ad8198072c3b8c74746dd94d203e83e70decd2fccc66904c6d2e421e6533d01643f01ae78a6136136f9b21b259c52b1549d50d7eb34bc5a96551a1738420f9f2c337c574207cb66cb271b0b6bf4e42b18ae907e25a1a3545eb57f44f14290f853be812b14fe51739004437876a1c81f1dd2b29b22cedd2187fae870b7b92134490a829dbe0ff2a5c564c949372592a089640917157d8363044b098a888974cbd095d6ef7068b7792f7a6089b64e51683dbbb11b89fc645b21d24af18e00a18211ecb4bca7d17df76db2ba45aff38245a8583deb65aafcf07189f27eae6adcdc8b8daaf3b8d7495bc6e35b69314a76c65e261cd0b73b092b49b3a999f710cabce4aed6f13fedd1858862b81e0d7d7fe3eb47bfd9a3bd43233e1219605af45e3416e9e7546802f6e5c822dc0fa1785412150b1bea64bf3a0181d35a6375185e45ee3f9c2943fdbac5b311d8c9ccb1efb11f9532caaa54a31b9cb159255894ad8b179914888803eb23b4f438e127902f5ae15c15c7b9c357efc5665a182b452641630df82745d068e2c4edcb37b30b6aa8bf36a5285023c8461c1003144c4a366ef6abcb85ebb26e78ed545a4217a6906d9f94e9a5b3def770950be23d4cc1fe39603a5fecec9c917d630d2bd65c2e0b9a6fcfdec444ef59bb6974fadbcbd0640c63e6455ff971f1302432b9c45165f84310f2a4e0e3152e84b8749befeec31ff0c6d887ac3c99345992427e3af5e2dc0f8bbd099c63e768cb30f1d6dcb76ab0dc219cae387595a803504fa86e99b6ddaa4cb40c7a7e835005de5dcd169ac9f195134d4f6c2abc25c7775486550429b895333cbc0c2acef64db533afcb9dbf5a6e8b0f468edf0aa8831330dcefbd34ce10c3fe93854590913db8910cc9b8ae7e4b6d969ca1de391695c19f24957d229c3e077e8adcae77f116079a821d28f2a2e001790397d0e4631e5b6b6c23ab79356071713406b03a00e9c3ea8c9a9f3aae9871480bc70560d212f43bbe3133e51ddee9a1f288bc933d6fa703cc0522297dcd75630e492422596790ca8d2dbba92d6728232cc9dd907daf329663f20165c3c1bc3292ac86670e01fcfc22c5d22830127ea694d2d4be6a4285ae7b3ece0dab7524c94f569372a9b90350099622427ef161d3e6ab15229581be1aecf2624732b6f34e1584886abae127cb8aa9603bac768bed22eb2486ba87fb80a0247c23c6c28c67eb8307c4d570a23857657acd120ee8f76f001f77f4431df812e7e01529a5977b439b4ff70c740ed0d8bf07ef4af427a027953401a7ed6d3a0017b97d504d740426308527703fee5a82e6da4709c778bf1a8ad708ed03eb57f300ec433a3c7a2fe2222073f35234eb9b92b08c9f2b8da438a5174730b0d5d161e3e274afba983fa7baef2810ae5aa62c64c7895502480f7166a0b229aa1080b822c0c85d22be7a8e1b853c0e31ed32d5f2188b58b8bb91688af1b0c079a00fa1a3b9526572da013d9e85270d5a6915b56ee3699a7b4d55c9206edb8791747200e1cea80b51f21f933ddfbc97def127ae5a9c12a28739bbf80e8078339be751537eb1388eddef9493fae476ae604aa3238ede4aa4598f809975651d12a17caf74d348daa38fe3eade103caa8926312a3eaacae30aac62b57a7c88baae971a3666bd5c25f26f9ab5146e3af9229127f15f124fcd5b15dc15f9dc9945e91ef575709545ddbd07ac2a809a7bff7636a573673276a00bae25065e5aa1b3c7af94608d7901d1b2f6a3a3f27bcd3e5ac24f98ea295edf73401138fe9b98e228f0f7d503ffd6c646e0e851027292d5935384daea04e3b972ffd2531c31b44ce28401d410af0e235be6544f7938f834ef1c3a9a3c10b39f6571e9b9bfb38eb9d3e89f0181446826559c91a2cf168d59c18a3926eb75f8d2967e6c59d164b7df78d53e5348a79f72d38fc002caa6e63bb3d65a1c15205ce1d12b2a3e0deeb7c2988da583a074b05013aded003864e1ff4e2bb1070b341436d5fc53a40c5809be5936a367121226218cf6c6764dc6aa0e57a12fec1bb812f7faeab96a0e8d3b60b437912a025a31a759a5d8fb02e5383779febd383ad946dccc6cf63e34b1d9b29dd188dd9a8a1a04012838f6b860ef4422ff47e1d9176073676231ad9786bd465cdbf64d111f2cfc2d2faf43021605b72f5edfdd45180faf7ba964128a99eaa5fd6aa4c34661e2dbb1f9c29b038f74fdda1881c5a57f89453e26402ec180b86bac1c660e9d2fbe7aa239213a18bd1ce68172bc4e9d2099229b62b4ef7744cbcbf45f7d9d0d6b30f5e8f13af29e49398b6e9db65cbdb80551296bdcdb66c1b67cf83ad6fe7578a5871b1dda1f03108dd60f610596755d68b7c1999e22e02f629048c5b8d20fdec1930bc80582f369ff282bf8cadd9568726da5dba14a102883ee8b299a6347f69760b7d6e7ec893f31a3d43a0175365c260db2677c39ddace4ea1e6313138d58b52cfa06a7445b15bd2846eb9ae3aa63bebb058dc3b4508787a428c0166d0c8f5b4e39452c368b98ae0ca638acdfa35242e061efa7cbf058558bcf983ab8aa0bf681e43c291208fd66335cd2fe44d5bc96a1a48df6dfd8814f16447bdbebda5356cf813730287ef0e4d7d71aedff1bbd90c27ac90560583e890af5da40a5aee6cf7a92b930296c5ee46d43b902007d73a18e021104e4eb893a64f8c61e511c029d5df8834d1beec8256cfa0f59561c5b39a09e1590a6463f0cc9a24dc16231b6d4b72edb3b7b58caf73870c6453d412d2fa2b79f3a5b14469eed4d05a2b972c41a9f190ab0d9804f077f8fcaf93997e6ab020c04be7d7750e4d2dcabd08db6000f810b9d0546e926ba9a7ec03cc6f410a9315e8e87ffedc37e50959630bc17e957ae78cf5580e2b50453500a610df22257f82a730b9e092755548c0fb12a4dc2d16c35b0e1069e5bff3c958c8f488642a37c4e0ec043b98bc2705af87d058de4204385710dceae18d8744a3c3d1b8d16307a9c1708cc5a062ece1b8c386951bccd2199f235057a34d38bd85f8eedc289da183cab0b0514aa84b8924e54cca0b96c6d038fe4d4b02c9e31cffd3b0342546cf7b6d09ccc2a4c5a4ae495e3acbc8b722b448224fd5a64ae7650f3db694aee0916794f385df26ed8c04f038334766a703e20373f2276bbb4dadbb520d9bcf68ef398ee062c6893968480dc455d45c69624275c1fe50d485ca6d0357a2a9097344d2fcaf2de14a3fbf7217cd588c3fecd7bbd0f771356fea4a431b90882b97bfe1817ce3836c17af2b8129b36544774c130ec3c84f15eaa5298b03c764274abb97a281b3915c9fcd7662c219596fc8d3659e38c656097e999aa3eca628fce0fccbdb59c9084e6d6f86a35a1bf5103be7242cebb87299f0254c12322b47b74e817957afd46c1e50874aa570e6c76f47fe787800a09eff3e8b4b7f56ff634f9ba9de0a8798855324e763ba7cdb051baaec4442ac2099c8f36f7ba7707e6e17778955421fa6688bebadc42793a0b2e4ac02f5b6f365ad7a34474ff9bad665d838735d6a2448cd0f6dc40824497c998685bf38fd7e2962794202e8fb794d5a0c8f79e02e6a0a2cdd706ac37f7a0e797947523f23499cc80fc0e71c371d80042955ee1b9f2047cd7af69d44345774bd7c0d693c838b0f899c7e50747a0b29a14900da91b09a7d431e691fa5a5273567ab1226774a09382bdaf2f15348d36fdd38d4e17d75dd89f6c7287b3de5df807b8fda2edf408eb2b716168f05612a09352db5fd15ca9cadc90a37ad38bc9042a331f0ee4de3d43869035a9d2ee66016557c8c221300e8b913c08776e661f98af236568c745eb6a8050268dfee2d124724eff63a071c60bf378ef7024fb54b4543138b2654e178effab3bae4b188cce01cb5b4f2331b8e3e697c3aa6521a0683bc70b33b1685fdf84e679894eec9b3fd450c62c1dc0560dcfb2e0e5027141ad1ba2584b7d95567e0e6cfd8b454d097f1bfd63b1789f2121d981e338e975622961eea474682896cf010a0a584c4cf66192c37ee3c667ca18bb38c7b909ed7c07689d2a1577f43c23d42ee8b12818421943730fbd9edd234261ec9aae0e41ae2c5fdcfc5b5a0cae37d8cd6bb46408df3756884468aed7059dd3cca5d8195cc56a00901555eca96562b2ea5390e1f578baeb8cafc06373166b90fc1fd2bf7bd97deaab1f2742fabb9f039d6ea4572d8577c7aa4bb9632f1a4ca68dfa1ace30a015fadfc69104cf289b4da4ed3a58a7a3c3172ba73fcdfd6c6c60d01a3c1f093219fee9cf8b5b43f874aa72a485b62e44e0908dcd8beee845c37e31265be3a09afd0620d2621c2c78aa8f1903d1660dedb37bd6a84efc91d2e51dcf3954d31b961f3f204a8fe5e9c564b9b417d215a458a0ec496d714d0267a521c67f79344c8f3f4da26fc429f0a10bf32627adc467706e173dccc01a67f043670d5a4e9fa42b9bf53fc22d92a59512d1ae9badf891e08c401077316d2676947ec6c40a48f0a6638485e00d2c2d630a748aa253cb5a3bf965500eb3e423b48da05f8f6be52e99134e1a5193b2003536055448c4e053a10b911acc9243c6750411ee095c66c400c7d547dabcb418395a219e600ce2008993133606a46e8580e8cabb7b43c649acfe7418d7ea7b2ead224dfcbedae4f8d77f0aa0d9a4b8fcb60fad924edb1e5e8d68422b63833228aba72ca8f46ee180807c65e163063f6f16b18ea5223ca6ab3e3e2313033d4d047dc6f0ec51c634971863921b3969acf99e5164f363c26fc057e3350806b105a4133004f29fd66dba18f0a8665610d8028b2be583655b2f343a1c4d6623b397588548d40f87eb4cefd6d9567c2c1e1196b994af6522985b51247e4e58b3f80334230b1b234fb160b2845fe786dc54fa28034acc1139650cde932ce6e32004631d06917c95abdd6496529564585b31d0560226474009f96c625d85dcc5b551c0cb397e4332e69ae4faf76f2b25dac300bb46180050a97c9826e16a1abd9322d368b96bf54d3aed0bbc2440c866f7b86066b630cf35fcfba657a69489eea2d3a2bd10499e017ca5d426bfda7bc16846306c657604ea7cfa0ce0c83c7a5c6533f95821030e94984190b019f5b502826e1ae5428f50bbd324a9337dfc8ee8002564d810e0e3dcd89fb66ab3e5c23012b95cd42dfacea0a1ac1641ce14ea8c3c6f229011362614e1667603011c3a0de7a9ed665681017699a4e180dbec59e35736e3daa93e33c38c65c2efa086cd9ab284d29ed1e1c09f5fa08e5bd90efab856535c9c40a4cd979331e9c5a34ce6570e447c3c4a09f4bd2a133c2eaee88225bc0bbd7af8f2d4dd5ba8864542d7532452f52c5ea721246580619dd56bc0d8e9a3f21891d61cd7fc7453736f92e08cae8d0a9277c01e05e8f4da831478c5144819ecd0d225028b60a932c0812fb41de5e3376699507d8bb68c5332fa3376048db008156050c9990e2c7bc8014de04a84de8b6418716fcb053ef3d33147ac7041c737dc42e4a95d4a32ddbbe982882f51dc59139a6e9f6d49038cf00249e0fadb45061cc3cab341ba2fcf1ff9e68a3dab6edd9c005c11b393860efd206b9fb7c7ef4431a7f52615bebced4e61f40d22cc7d292661cd0640a9833f19d701020ca7c9b8e47178688b735dc8b0f837096e0fc0078f508cd833c4d7409668188857f9f50efcbd084b0eb86717ed99017819049ecb57a12cb9610820c0b85084ea380756c77a13b0cd41355e632a639a2a77276b250c3ab1f023a363e7b7eba11d19afe0f436c8fcc1f149111f77a9fb5533d57fb32bcca6f5967c7b33123409afd84a78678027b5a00da9ded76e04582ffc1e297942200b751769d8db0d95e2ef4b1997356309664dec9a9c62ece9ccc0bc86fbb7a5606bc24a2491f62ab218ef99ed3016b8aa053596253ce26eec46a5d08024806bb4f9c9f0ce218911aeee9ad512545d2d5b45d0946a18774b54d11cd6c88ad61e3565bfd2ea67d0440badf37fc96c6dff521bf5459eefa1a18a14cc266c00b41685ba97f0bb84f70995d68dd863cd70b45cc862528568d08c7bf3613ccb6c3c9e4b1efaaa5a0b7a3ab0d644d58db643c8c30056ae3b9e9bad5d4134a4c8e72bbcc0dd9de142b65e0e5e2d2413f9954574c46527eb1f18508e2e9fc97559f9a50de34d76f9aea0fb8c429eea868d939013b3bbed742d7e986b1ae9ead9b8e3339d8d2c72719138a9eca084f37c27924574040b2fefbf3605d6e83cf236d485addcb5cc0c438ab11cb3fa14391e64cc478ac50a10645710e624fe1c1a87e4f6e38d373b2b12f2de3c3c259617656e3d88ee841254bd7a13e8c8ba221c68a832e38e7bbbdeebaa254ada09b230c16c0d16d69696300a6cc65d08450199ed2888c35348c5f44d2060fdd31f26ed3492fc4f5ecaa3968900fc8c4b5d143033ce6b6a0bd3e633c5cec06c040784e48a2c60c09e83755c651b5d449ddd24ac556ba7425f71e4b97725b8bc383574daa49ba0e2d3843db1f19b721bd7470a5ad50c43d75c5915a3a9afacc846225933b9ed51995956f706257bf66ada40ffaec3743e24c2b8362563cdef3b2b0a06c2194ce5f450ed6342d840504b77a0c8db2543b6f8a7b5aea94334e74b38af4796c1f314cff007830ffd5430f21d9b6b09c3571aac329712cce6ff37d2549e38f2846c48510ed953b51ad436d643e8e4b7caba37d7ad05620c83bcfe189b2dd9193e70768598baee3ac7dcd11c5c823086054a28e5953122524439eb56d914e31e755c946fdc0a9c18e52ca8d9d2c9553aa0ed2b8da2bd37b0456b6cb8410b522123996a9ac660d74367ee4f0414c34ccf2274e5344d12ff63c0a2825d87a2b1d45743311797e66c8df20449478c79ffa02a7d61eeeb6255b81b1af6292f5a7e11a94254157ac9054660529fe828af7eb07e4755c5f10fdac7a8dca19619f4cc57a3b3f33d66e9fa2c5a994251abcfbdf2885a0ddc2a33057d90a5810852615c033ee50806b060b3191b9dccda2c2937490345a9093c94a142cc1932e7143053e2ca8559a98453dd2b4950e318b9ec8d9fcac81d50e3f60355203edf601b4d3bd7064c68a50f462a10cf3454e23ce69dc4cc9171a558484c45e0a3d331d3693462984e10404876db807889fc50c03cd5cb02eff49d9c124142434df0c245f8921c11197db8991b1f856957f81314241c621b8838e5a63ff756144bf5a37690ba2a65c827a987772cae00b9a58c88700895399fcc4d6a0e008d6001307566b95b9409f1b38729305a4b4333180c3835064c0184a04be71b03847e8a0cca476ac44706f7b22b50c25b7844972b667d9205f59d2cd32f24eda9a2f3e18b9641b445ca6515a10cf1fe1769931bf2f949d910973b7c2cf08a98c621a0ba11aff63962efba031d98b2d824bec792eeb0a6231665ef7fef579ae8c660094f867e7c4b03679cb54350e6a70449097491d18d301f48c88ba49110ca9a990fc8880f5bcb4bf6ad52d4d454d40ea653a4f546a430635ba820a4d5f1216b48ecddfc4e14788850469c3dae4c165a687e8890a8ecc9d9b4d94ab69535fd5c50f9d45e8d6af8f3c44aec8db784554c1671a1999d7cfaaae25a1457b30d3c5e29c62930189b20714034c30e17ac79b9cfa1b8998e9bf02e000ae68386cdc399f3f0cf7684f68b538ddb615272fdcdebd3c1b525408dd0debab19cefa39a40416a9540605cb163752e11fbb5c4f9b3079dedd8e6167ddcbf250d419a0be4896762d36e08fca83ded22c908704ab082bd7f54e1aa65e7aa5087f3b3146ca4095ee5739fca11f8da17da1c8329c9b870056df38b940252715679280013111c6754e23670197979503879518ccc76034c0e5f49ad256e3c0b18442714b63a3e476c906aa2fde4d02a18657bb8c8e64d93181a39a3930ce71bb61c928a41340160d1f0ddc527b166e493ba5277882dce480ad790b54742b2de4d493c0a5227ffa6809e86cb860da8a68bc5d0a2645bab35a57973f9b51852977f55b64733c28d88459b706d1aaa50aee66126ae0b90098132930bb3eee3479b79bb00ad16500770095f371973d268b89f9f9bd1720f95a336ef71fa88fb3e6e5a8d4bc9698904dd5a0fc482d874282b10f7557d40da26f86506074248cd7baa2a65ab954bb286381c0d811d84f02d32cf1505d3c54961c529334276a33f8ed34b01c6a2d7b27349cb087af753a73cdd8be70927e64e3f445283a822957a1490bc46380c363e2e5932f071d4ee4372edf535fbe64c364a4b99de31f8ff88653b31536136d0af15733ffe462f8c61b2292d1a5dd75812f188c9926dab01ef12882a9a1bbdf0b8871488e9ea391081b045c41686216eea40c1675d09a7c228ce501a1134e230bdac21e9b8c898580799b41ead3480ec54a3878f7833612e33ed0cf6941618616838510ae96f4bee10cf98e5c8332c3fe5d11d3d8ce472a250ecc23de7a732405f5a20a52d9ce8da83ce8505b52e13002a80b3401393e124cd9850a7db9624455dc2f13030ae1dafd513bc7d8d5fba730bc4b2b961fc6621f0f37b85b9e9c54ee2cf431a694d00c0a32a4a3ee7f405e6a66f972978ea3548f9b8c65c7aab890658f3c165279d03f80ec6d6995e318030dd9c0c3ec304a62a6fb16cf893aefc1a88a49f4dc1e398398e62df630e4c264bd2dc6e1736f1cf8b1830769d5f108b00f30f8354cff293b2b9ac5de3faa52a454d2bfa659d0b27122807f21d59e7153a4e61e64582f4c7c0efd21a4483a17bc44b3c0e0baf1fa8063642819d3ea1e89385b5eabbf327378ce32885a54e8cae539d8efcf797e3e372f67fbf9ce3d106d3e42d8e1610aff8d05470e5a8b53db88ea00737a27adb290cf5962c9909ffe1f29c25665ea55188faa4424cd6ade4c372b77e33a0eacec6d0adc934e6c26f1a5398b5700f3112199589d004e1f02c83da5b4c5a275ad9ed0785cdbd74e1c68a2213a756523e6cd14acaa06a2ca16ce4deb2402017d7fd244af980640354d8640515718d6d44b0301ed7705e92de34fd948e1fb1a64c8a247d99f4d48d94fa039ad5971e94a7c518ce7a3c49aa09458d47be7fd05ddb720d5ddccd8d11777a73397adf62e9637a2048e518ca38cd16450fda553ab85043503c2434d2985e343114d19fbcc60fe549659a0f6be730d578d8f1a70c8892b85b837b2a0af3efa18b2128c771c437e8be76d89e0420eb2a39dfe8f65056b6bf4be0eb73e891458f3bf6582056bf33d2e11b34bf5e1b59a81bf94615651cf37947d1653effbc93e969feb588ddb7950971833c27f4e46590639130208def54a13b3d5b2c90af5bfabc9867313ef235ca431793abf224f62643d8baf613dfef1b77c18705d2cf08cb8aff53d062b1ee2dfe6019327e462f5f5f82d117013dd7f06ea39ab43ac661eb636e01fe8c6e76ed05f78baaa3abf81cccbf2f6ad045b61bf0fff5c8ca9050a61456b85e0063fdca2ae740852851d41be60b1552a087c416136ccaadfcb822fdebc35f758682bdeb6782290b9bdb66356c41d7e376d0caddb1c02eb1bc062a375cc580f861a901e2c008b4bfc94da4e07e0f6018d05a2a13ee23657062a5ae5142ad80f2ad2f60fbcc9ed9064c27e603dfd95cf472e86c54572058f5959810ffa6f0f11cc8d5cedc7bfb0ac7f33a894880bd8cf71c3684004c25548434a5b048f2064e690aa6fd9b33db9c3e1db1f2ca666ba0f0f09111164c0e2ea3fbf96ab67a9ec85681088402acfdd24226b5a6513f80bdbe46ae3769725d717d709ccbd79c8d3fc574e49dcf655b5bc22423c11e43d96179bd4c92b71c3d73d0b4863c50158d6e32cb8c9a98f0ff6dde7a4d1b5bb74b3796f3ab40634fc689b0670e1704da724e841dbffe24ced8e0ea8a5b7b37b0018db1d3f62ccaf5cf85f15509cdbd2eb3d4ecf427f0d248d0e3d55e7841fe4468a2a861fd8d670b7aad02bddba313c751ac1f711c3f36ecfa95585df2976fac1d1a4152374a26d16ee926ee4bf44ccf79cd419749e46612f95d26b37ce16274983bb2445f3d05dacb2e55b31f15ca2adfa8780c330ecb1eaccc86f9097d48757cf8fc1e74d57c71fd3339bc7a3498fa0c8d860d790421116c8fe23741de99dd6adfa13d8080e6a80ef989d206da324814b1bce0f2a832a839091a8e28a863c9aed42c61dea24aecf24f629e5953afe941bb63898631d2917caeed6b602ca0cc72c940d5e5f5985d699d183bc699f0bcd47e95be9a9aaed60666ee7aded001a1cedc89ac8bd832a7fa88f1175ec9f5426658c53fb83ca683f1d2dd072f50aac4bd02e36e01be754cce1c35b82b188c801f27ce8b084b5d1cc3ea0c2721349e8048903bd002e55d5c14e5aa30d12b77334c6296aebc961fc9ba5aee191df2d0bc1f6762435ceacd3ba8ac97f008a311793dc340127501298095e8d491cdd3e5b16a6bde1cef59f10c08e6a1659bfc20eff5576ac220cca6b1adaa6b308b8d896f1f444ba352913c1fca946444c0497602bed783c7896797fadb77dbe63f3fc79c73389e6d151c28aacf333607eff31653a45d80fc4b01d237284d9feffd5c6c2d9f52af13d8a946df770cafd0bbf357f442001f0032e26650d800ca172a81597c1d6ffdcfeb3a8ac0c4928fa59919015aac567e84ff9a09affba2d03aad57af86b30a885e6de48a115d94dcb6e3772f51af80022f2570459023f41b680b4bc2bfbd75cc2ef72b7582cbf30ce292b18f1c0d0a986a38f0a4545d4a1ce1c51c855b6b0abbd517a1b84845ca93432f828d5579c7253fe8194c6f5125cc265b6bf686055ec69b652dc21ace691e21c6c0b609a81573f5e80916cce7e33fd6ef2cc84c7edb5b1a3cecc3875b201a4118f644798fc77a820ad121e8b86c233b3b36c33664854537f860333556e53af7dd6187626df8e79cf9c92eeb1e812ba8483cf4ea7b303cfd6c3de93372d43b0b68ae917539f71bfa2000bf317addbb07fe4358f8bd671ad67c4c88e8afb0f6e8904da54610647629d99772ffd3e1a54a0828ec59cb8a8e03818c326199b3434f87e1e0b220e9cfeca3ecea7db7f7f52834659cb70a996f05e59b36251f4987eb7d9d0b8337337d4f1aebe4e24584eef7a7194863e897a12fb75497cdf9700ed982fd6890009140d9812c339721c3119a12ca871c4d75ce907a20b71ef7f908a67108d338dc8abb92205fe56809bd848aa91fa0d4683cae4b486eff0a71a77271a94b4cbea5067872e914cbc30df47ca94bcbc634b317f457126ec8992416ebd05d690a20ccc7ae69e30f05f4c50158a59b62fd8f1135ac97a5aa2c649b6e44031149b240c0200becf2fc24072891ccdb3cbd028ff77ab8b25b39c5c4ce03f9c9558ce7be94f66c96ca6366362463c9159c3464ff9ae2cb340dadde2e69054cdacc7a2107c9787ea8566567c519b2bda9d6e0b38c35a84cf34cd2c15bc35d6e4f2ecf8545df0f1132807626675049e42358a2bb8f8ce20e36c22bc99451124493c5b22efae7bb27033c4c19703de65535cbb94d67ac1c98df5cd5860d8cb9dea926266201a926585651a2550ef61aa1942e1229761590f6ed1d512579c2152981cb370f83870358e29ed8a929c30c1db300702c4be41b5a4c312f2c409ec3022bf340579a6d106fd391945c31fff9e2eb9c16dfca2ad1a0824769a5243d3bb0bd2745703effa8468bd18cdbfdc7fadd29611de5d9a23f8e9834eb19ba6c9986eac9d2e9bdad24cac74d368d2cad8c1ec2ed460185a5d685a8213c1ca1ed60986c7c71c32dce09cb33003a67aaa8adadd271acb0e4f36def85cbb0c9fd981c1cc7d71bcd4c6070f8ab3d43d82cb2c7f249eef7234078bbb50a6c7d1ead2e132cb8a809df6253746b9d4e53bd6d67e3afd9c871dde09c419afac1bb2c56e5cc905f35250705b5c60ff643c07ecc7bb200b5247713840bff430fd9f0f8a514b07d222e1a6779a611ab3b6f903fc37fcd976ff1744324eb92dee86f500a0258052c09117b20c3d17033a303212e0ba408a0ae64d051c60a4ff0347d2ec34f482d2d640d3e53d02a0b083da623116190a11e74ee6b33e8ea03d7781417c79a1ab33a1513177a26ffb9a29c2ca7fb7c2c7a268f3e6631b7295b34bbf4bc2c8ff3c9c388ebb6f7e2e90861ee0c7d9762f20d3ae3267ed450043a93e008fd4871917dd31e318b0e1a7389f3a0aadef41eabb3c8e8fdea9068174b8b1db4eece536d1279d29e0554830cf0237bc615bf24cfabde1f63637fe73268e711ca22db92c05c69299416a3aab455b8289216ab9a5702c5d4753d5e42c65499dcc0f94baa4673af1f976d2fe9a981594f0c54289339eb6073c8acd825f90f0026179eb9d2e87e5eb873c1b22fb48d60bc412623aad5420c14bfc777d2c575d67442865212249cdeee479a27c94a177829a02be159909f9396d815eb89636d403710336be30ca3ae98c8c70c81f61925941c67ad6bcc8f45915a642825838a909e2b2079c1287007573f4e10edfdca9218103630cc652be3918c81e5485864d892e68bfa43253737a18bf80d841d434f22d0f9ccfee00995893a27521b7631fb7927fbee078d2d379323882cb7f0413ca71414e58f44fee1d9263a8fff21501cf39256d2e334eb134155d319ea4c62384ed70c80e2b5fb5c3ce3825329a50413149f098634d0ef7b9d4e1f0a8fa6340ddf2208b73836d7e1083c988850d837e3f6d07215cfa92609783fbac9af58f4901295c0531ad7484cc1185666244d5e74b00ac8a9e531b5b464c4a63bafc59d200a2608aed01750ce909a686112f064df11728c8800d5e8a04f4f1b1b2713deffc9b9c2cdc750f105b561127b275dcbdd43e9d28b846e2d425046519db3bfda6fce3d8a63e4ae372b09ef55588b8745a38df39d29ac3b2250f9ea227bbd063f5c83b7e598a29d1b5ddce3b3f99ff27667c03bc18fb87357ea3f1dd1ec4226e68947b50824d256b9cee73a52807f8c49c1e7130295a415fc07d3260d8f904e8a3a766f6a0680bee233fbb76a6d67ce202ea7fa6776f39bc94d8314144b72111e5e6a19af97748098c099263c03412573a8e4436607297714f07e91edacada66eb418afec0b425f4c8be864ffa16579527eeb5accf39176402fb3a301f95f86279ee699adf5a39ff9af596ccfe00184038f7d40c6133c656ecbe2afa8b7de8a3a53bf2c6931bbd103ca134e4599f496e70deea4ccb73bb677ec62e07c42c42d7652e09b60035fb966252538702277b8d9ad5926ab0d411b4b75c00de7a977a239c96147d04f6284bb8c2f5418942d6d7d172c879e63501fe0a0ae8bb4e2273a0ddedab9e5c56097650548a854c43eb8d581cc95b18952b53ec7c302adf14b86c7b6e218b1e9642d4d4db5fd2c71d861548b99654bc47a0d36f342d381854f45aa54a8b21913aeebced2bc3b6f401238e98651c2ff0d8ac305aa16b2eec9f7450e8e80c826165e9939f2f7497d6ea0b9c1fba6cc2814a8bed139c7de222f9cfc69531989ef7283320bbc0e1184cdee61b3e44d177b574787179834793f5494a11b3deb6de7d1a85e67eb163d43ed67780b9848e14f7f4d22479ea244b5edfce56d94468dff6f724341c3511124881b90102a5b6ddf40d24785f34439b4673a75a35b39a311840ecde8372b0607d878f5b9a04913a6c56402b9adaab505e9ada39a6d2590b0d9e3b3e0c99daa8516728a8cc56d63a53df0e761b9f73697d8e4767752b554faa0ed39c8b259b62db8b8ab17d858e1baf2335ed9b628125c8061947dc98b365705ff09f31678461e7524f7c2d754ca6b154bbef0eeb06e8938e7a8696406688ed4d4ba4e95668bdca8edcbe024f91248a99049dc60f8f3ee5845f025c546f642c7e3149a5314479b78c523848ef28fbba20ab31b0a1463740aa572c7136565e88cebe02efffb7bcc07d7001583c2147ed6279ae0cf5c9c07185ff3ec13e2968a340820576eb06518cd1b95e97cc42f7c76df709dc915b5c701b7d14f923b810da605cafacc030ebc57c91871bb58baefbe585664802977bc3bd728cfbd12808af63f6b54fa22a394cf82b90d0d2a6c3839c6fbfdf96ff65f44495524a88067c42aa83a3d4a8b22669e76216a367e1a783bc3e27b1a76353815c7a3b79ae375c9c256a5f638e604aaea5e523f00904b10aa3f08a8db85f2458010ae7dca799cc62c8c2ff2a28d642d3b8aa264aca9d60e66638039b4d148f9e1aa55ec2175168f8750435ca82e25fe4aa368c063a80fb64781f0b8290d801cee47833bd8687eeb281b3e1cadf0dcb408ac4e7d5417ea585266d54a8c154fd3a757001412cce3b41e30b50f3be805a6a4ef7b7beef928fdc1d57b70e5386da46ae0566755986f5205445025762dc9316e61ff27e6218e977c5a002f2eb5f3257375036628a5a5d19fcf985018962da0a58f3959d2cd5fdb86a9c76d464d49fe2f89eab751118a001efcae3ee993173b0a9c4e1ab1fdf1f94db2aeda80987d991297661e0764306ca18631baad78ba258bafd22ef8c9da6223f33509b3faa183defe70196d0a63213a82c857504acaab4f583434aa255b48f170e439128bde71659c1038e06cf0d007d187c35eb946306c6e01a23124f4b13c3c244c7fe22b549a32056c8138dc1da91566cdb16edec4e89b5312752784440b4ac284f1acd469ded2683d1cc24fc15ad8907da477c8d513fec8496255d15e57144320b81141e4e100189da88c404695fe274ce3d59a44bce268241d44609cc0a944375fa430f01d7d82184a1bf4ebfbd1c8558448a983eaadded4309e3af0ad1aa8a1d697ba40c8dce535de8d74045632bb490719709e170d56d4a8f228a3bf6cf86d53394a04b32bf14c3e6fd6dfc37b2358549ca5950da6a5df24977eed92d633a8a65d8dd9b7b9349e9249077ac9b9d89cf948b66229680057d6a733eb81a79b003e29b4473d4b6d41440fb3cdadeb1ec6dd094bfd40ff79d124dc44d9d2de8850e71dd0a71186e034feeada24f18cb971ebbee6bb86571b182fce7477949d99d4c13f213234104eac89a417e151f8c76701b230b188c5edf3ba6655684ed602fd48688a6ad2911257ddf0a11f4c7a0ed8d7c6cea17d90bfc8db2484724c4e1d3270306de007fd7ff4150bb8566c9fb0d8a339acc97872d6214f1f1bdc430a690691a5d37c0c3ad6175e58908a3f5157a63ef3a00561fbe65209d77c22c86251b63d8ccfc22056bf779e791475653fc00a23cd869ccdbd09017b506a30269d3c45747054fab1b533d5a2405d067dd638486a393d016c0215a0c92b95ee0b5f922be1bfbe1c690a4874f1768848c2834c678fe601bd2c404103fb2d16e517106b24f6f68632ed048a3759d96cb9b5e69f430c4f8d3b8c470b8fce6d89ee359597751afeef9691d873337013905bfb817799346cd79f965b1331ba442ec7725dec09fa79ebcec5dd8b3ecbf86b45173de2e2309af105e61e65c46fefd786e509dbb8e1324b2f2a52b3c81db0b90bb99cec43d7fa14cc346bd5e86791eca286b06606788e5b419f865bdbc003034adcef57ddcc1ebc9e60d785f9e11932dd31ab5f12e7755686bccdceae40f361b192ae4d8a6236329d81ccf08da6c6b576077bb46b18fe7a4e9881dc399db9b067b5f0c352b88b1b18d72375cc7109b1b94e39e534cdb9ffb339d169e8525d089fe24b4ab029f5c8dc6389f7365d8b62bc9a151af2f8624cb49f867347237ec4524ba61b0d4b1b8137e562ba26010c6579a2a6b6d43423374ddc194cb4c4f4417a6629997f939d278cf8b50a70e2ec7ce6611a5a02343b97b20a9e9f95265a11e143206e2b340286086466214a33d3696c905708de1258572ee8c963be41c0ffdd466f487346d70f96dc04c697507f94582953acf757c39c0ad091ade992c928e7af5a04b082226aa94132ddf408f46ce409a89d6222f80f0b992f1a325760971d0d34ba021db74e93e0364311dc8362cf481dea11bb94df28c6040657460ed12414c0ab2b1c4005bb29d50561597edf508f68528d0194f626ba0abac23e8ff4c99be9b5e04830b492f90fbc1f30c23658310ee0631dcf3246391001c080802a2fb90b5ec746aba896b5cacb0877c54cf4eba181820d7a462b75d14069f95ec2073a099168e6c65d3ce45a401e18fe2b297e012a2f570fc9129201f5c60c0764429a9e70fcb5c221c284b78418848e507a13d496613d0fb92a01b1139a87d7000e32f811e63191892275e9db88da31819064740eacf92dc43384b7faf4100e915b60a10274e53525b481343a32a067308a768c8403a24af6236a20b0f714abd5d429d4015cddcde4968adbe03bbd83b24bcac6c1bb84da0ca644a524c1a2c8bf84f6348f6c1b4b8aab3fc090e2cbc19af28c4c910cc957a355fcde16d1fc69adae3f80b3ee27110d7b8f92ee5d57c3f0474d196e4c741a900d978e534fffeaa0148c7e161d861c01267e16f8f8db4668123c1037111db83796ca099bd5c23b6b1b259e728bb45732094084c6e9c39c215698a5ae9d0024f951b2269bbe51535caf0a5a494586d1ec355c39b5e1a6effaf4674fdcb7033f192c02c7be92c76fccd64907150149d392282aca03ee7e18e9aeb2e2a9316f060091336dbfa9732c0938bb60283176bb0443718588cebca75a01018f2ef8f5fe3bad6e0ef1e615d2c54351cfd0e381cb5bee126eafb28b17cec9fd4df71715f78e773cb76659cf7e36f932b2248c39400d03e4597497b4f5fcba8e6465d62ef98bef954a83ac455642dfd2483f849a87e027bd9a0c4499922671f849fcd9965ab26c4e7f91ce0343f1644132fdef6045aedc8788f4a4b86beb12b6fcb226b28631d62ed5b2282a91b28746bdde53fde46404ff7e0d16b10b229eb76e87629a163cce61c79431f6c6125418a31ce8868128899c3ca11a10c3a95d3f626b2ecd9b84656389d99297523ba3a6e3b88e131f62183bb3863c8a6c9613e4e57d15e37e5ef895cfa375a25adb3d2aa9e267f1f108afaeb8bd1181e5dd24ba4cbca85e08640819cbbf80f22b6b0c137683a91baec130c9389e3b70c6196564e6cb6cc220499146566703ca33f02f57e88a0daba4a277396248227caae66578a4c661ab1f076e15750511677a87322f41a130c1488a9771ed842724fd7bb6a7ea88b28fe505b6f9b541d2cf1e1d15df840caaab1ef90e439c86feffac4ab56e1706d4694b02aa9409c8a53a55585e3036429e5162f36894b6456b01c60fb5ac14a3e643dba7f87836db198908c0520d830e044c476bd2a7220d4845d969e029b79844c627b19f19e796ad119615bef1199ca4ad208af303ab0e0a1c3fd6e32af02dd1ea31f70cd9119c50a68d9dfae3ccdbe5cef25965731d88e3cf8c27252a6b0306762f44b3e246d9390991879f9e86aca76e2d6149643e19a7bd2132929e664064e78fcd3289b0a9c9d7bccab51f650439e314773f8bd39a4f1675c170616689b1db98301f60426f538d3931808c7055d573f42cb629cc10a7e1efeb5e27c368bcf85f569e1c226577660faf9950fc67d7670a8669118b0e58049667da96aaeec1a4f45d1831b8c2b573376f7b9c188ebcff5ca36b68cb8e1ab9a923cb22c8daf7ce9e9b72ab75c858d1e8855ba56653775b996cda185f913ab528ad34f79d48f4868ae1e5f3bb7a64e4944731675e1955473fcaa64c9955cf2085ec9ea09bc38a6da4f5682851f4ced52119ad55493a7b1ea4158f81d2310987eeb7b7768e341f70f11e8c76ab466b4f217ec8a2e3425a804566abeb4a50a457f6a7901b8763fc2b7a9985b4276339a69c368cd28cbe60317935c8d08d0050c78d786bea8a5f693de8a6ee45c3112348de1fd844384a5923e5d592d07314253b4168903b5a12ab54fa2c5632ad55df15a25186b3d22a4a071a34ad9a2f9886aa5faea2c1b13fda45bc428ccdb6175204a4d560fc82db6c951914c8c0dc1a6f067182cbe81279c746076832a6da4125625ddd3da6d08dc5f5b8cd55f21b9ee0027740e24c6378ab55a98fff96b845106eb6309c752a82fc14db61735249154d8ffdbd838151bcdfbab51680331f70368c579610359dc10817dd0ba1ffd1ea0b47511a511c530aade67b5b975e17acc4861f382633e86b66e441826b0f9535fadd2461a5bd04744e415be7d4fbf6484b6287b3b3f0b0e7b759bec86256cdcfac27f0e3f0c8c99f271154bfc9f7f30bb99c5b4ab84a689a1bb736ca68357d1efb45debb6ab472ddf70f8a58552689dbbc606a21174bb0ec333d3ba37c5293a0a180841822e7a02ee42a6fe37950b4a6812808dced75fb03a4316b4aa1662c76b9bc7ebc58f73c5e8971bfda96fc4517ad3e70431ad456894d8169fa13216f68063b07aa60f7fdd00ae57ed1eaeb761a3d66e14dab22b0ec84740b3e6be9c9fd8585ab7a046ba7d701fc1b8b962d9826d9788edd3f1e6c66e0b010428bc769d5f44ec9635c4ec3e50a7709560f650b98232646f26f8b071e2c2e5d6d0f211fc3dbae680f098ad31ecfda8c9af63a7fac56286b683cf063f393218e16c43439307a72d0e8ef1c4c1554928fafc17808c0df085e36b1395ca993d8e8a49ec375312aed736669c44a0762e214655b5533579c3b9050b7fd677f36c0b21840271b32d0f73859d5d0442105eb8096bfaaed92cac9fa1a864edbb90e13e02e78525143e16aa9d9dbe6b34c4409ebf381621d9657102aaac57dc99a157a8277cf1bd8b3e877b53df453b386501fe5b153129aac66c33594e0ea4b9b143fff1d15a18b1e825101f3a5ea19144fea60565a8aef0a21806858b1888f9f8970e51f0576035ac6cf5daa6e04827011c130e7c6d2ab9b64d2800bc2f24fd5bfbb549652ce825a07a7172376e9b68a5f6184c38fbdd08bb79f77d9ba5dd6f2ca05cee467a17eaa964a86516120ae17cc5644e031b9d01b71972ac86e2733b90ceb13f44ebf1a31d3da6d32561e6621bb8527306a84ceabec2d4c677088f44eeb0889670aa5957caa560e1285a77b928c08948bf64e99e38a44d5c5e68b41eb8d51416942c392b8a4ee16bc3b55a82add0ba1e542ba89756e6b8dd0459c96ce7c4a3c9f402125e6a5a0891af9d13147d8091414d3e73381c87a9e71882b50d82f1fad299e1308021190a413759ae8906d1866ac037ab268429ded994213ba7ccfdca8e0f64fa7c059229d08a4a6754353edd289c50944f10c2cf23e239501980136299587049547501cb605159be192152f328485c2122db3e95c9cf922c886c56c36a5bb88f3a265427b61112cb701e8939abae234a0ffd8144d75bd7fa1d79646c75a9edbe2ae7182f383a5661236eac4e9c275d9c39d112bf3a740518a879262fd51f10f4f09c92642fb55bf6fe0e969ad459a8c8b441c67c6c0a5310f727d2996fbeaa5afcb358ca90b28b8c16b3231f7564c4f7986807f5817ca39a710a0738de1e6d34c9a2b882be33f3cda92e99be9a5c33d8ca6fe22d1e844fe6c81ca4be143415121a03171c7798dd2edfc756e263b3ec8b54580bc811e192dfbe9dee712be96b21bbf7b021a7db23075399162b853f46b71fea0fbae460ad72541d58e2c8c43ca4b45d44099ed156b408b268657c8540fd50358f6dee29eb90767945dd4b361fc3e33f3d7ba5900e2b121b5f5041f339bd47f85b6631892c8f5b9c008b8892d8ce2baa1bb4271f4b1638a45c9a4fc56d841ca5a4daf09088a07f3a47867462826ef1bb2f08134078ca9586020aa9b09976c720f4eb21f186f3678e850631bd642d8655ddc18252cad4c93d0bba6fda70b89f13594af8c3e62150ae185e3431e5e47d1ab94515401bf16ea1f47f524bd6e57ca27d09f031247732bed1c6e73ca52e9d78ca6f91f6f2df9861c9aa0951aa509c98382b5fca3f9689f2227506da8761f5db19b2f27fff76b89033593a43270c23d3cf9fd5b50c330e22e80cb98a04c4b76548e564432e3ea4cceb1168eec76783473f068bf04b7404e007e34ce22e243b50a27beb65de0888f7b34c46fefcc42c124af8aa735501d1770143535309a38d51d7c9f04a78807311b9e29888d8fa67f6b9cfb677f1140b78dc8f39290c4c85fde57a21f55c32e52d24383c1a5a0008ca6bbb409db3d8f3a24f5e47510f8a5850debe4556553c86408cdd0afd8deae36ba6b4cfbd1e21ce59b976c2988a502b471fc9086a60a4de1b20d9454f999d2feedf108a10b78ee4f512235aef1be4612bfcaf0e207f47a4872a5b78a531c2a4f9b6fd25de80a1826299d29f51d562adbd9ae6574a6403ae42368b28b736c2dc0fc058ddbd0d14ba3a3fbc3fd0b7154801ca206673077d0ff503ac0635ca73aadae3a219d22a2bdaa2bd3042611b000a763069ddd503127c2e111796c40ddc28828047655352b1502b6adf79295b2e834ef98aedf2cc7c3940a367d2dca1750bbde67c806510d4de92a8751e154bc3f66cb9012980dc2a3d08ddb2ec9f64cdb01266771265369629a5fb8951e029796b17aee90c400a45bca5acfc81dfaef0059bf2854512e20206e9d909f777e3051feea592f29734e52346d1cb01f6ca96320f7f1731c53062f02970ad38694ce5d4172aac68c0b71a325aee27cf2ce89e7e83eea5317d8710a8e9484377cbc2fa694437d89995b3a00e5b0561439ca854d1e1d9874798e1b42ba24686736b18078fc0b7aca2a50733c36766cb95f1b348fc5c725de68eb4505d1f20f9048355dc8269249b40bfa2209894c26002f1c6eb4dfc1508b57f8ce97e2678dfbf0e987006d694f1aceae39dd3550bf22298c3d158a6afb5217def62c25729d8e821cee62f6a2c0bf196c983553255095b3b785a6562f70dac5b0e4cbc6c7eb6c33dcd51d5184937c0b43bae77dba97a2d68a54daab3af3d9882d6236c8cad58030a2a6e60ccef1fa4c6c1c47c939ee82ea34d743f83dd959404208c430545f6ab1481424429873190fbf36dd56dc21653804628225d3f2e4433b7e8442bc94d21c2c89e8bf57eefeb099e906ae4eecf329a84d876f8f43fd04d7577647212a7c603407024482df2e1e007e991b4195e4f4148e787e064c0b2a9031d5b802a8607247b204d13a0a880647ac8c8625450d960448fb31945316bb7ff964d7d688fe8ed0435c6009357cf345f9f7e14ca6b0eff3a8c4a2a115216eeb5d47e9b8a430970061f980a57a2f900894e16dd7422bc98d16e731a191d7e4c7f799d4c68befe1a99e0387bf36120539f45c914197cfbcd603721e5de85a36184f3b4e110a5095870580168d67800ca54b5ad1667434246dda18eda4d0042ae720813fd55c4aafc005757e6639be765d28e1664f803ff105fd65438025932992371773da55141946002cffc90544cb539973c7c5328fe46800141a3a6045a01ea1a563597eb7b2f4ff3970604123df1a2fb598ff4126ae4cdcb8c36c4903dd6379cf1c669d9a06d3e3bb6dd3daa45443a85d6673c1065edd75c2152f47f0565d33e5a24528d5e3d60e4363dc580b5136e3e9751d2a106c2d4f0758c5b936cf6da09b9588cef5b82a811b0268ffa4d0d4d7bf1d884ceb5b3bb15c2319a86648dbc31179e3f1aab17b525ccf678c6b3d58c9f300860795f2077dd1ffb7a48818995455b665ff7ce8ee3d8889283b12c7a99d1dd5fb864158ca06599794e159e8ff9de83441061285d4633fdf73f55c8a591c859b2d862c8487690e1ff15c85dad3407bc5b794b62e9824e3cf07c1bda6e8112e0a86f529adb6da3405846773d911ad15859b28b3b6183f032713427e546c9a491f426a124762b285e6f3613bb1988f0ccd9b1f704c33d1bffb6b5e82eae5ff301598ef76c1d1e102714e305a208227e4c930603fbc9b1195890bc2be2be08bedfd7be27ecd3f819b0590686e48b8ec41c1403e035d6cdd0af41ca824f3a45779cd493c3aa634bcdcaa8583fd2d07dc73fb9f6ef37bd71a74dd2810ee7a5c9bd796a4ed5a10412a1d4dc81a1f2f7f8ced00f7f680604c3a0d22c552d3d26a0d7eca77b0b905e8956a718852c7a5ce56b0337ff74213b06eb5f7ce50112f1704300e103c54c4be710b58118bb0f414fc2babb614857f8bcf944fb9d9c0355636811b75f6fb5e084565b970d3936bc38f04c821d95599d712b6ca73b70b61403e41867823c2240967d6ac2ec3ee08e19ad90ae07feecd251c960279e99b57773a6cdc802f207021901a498725506f58fd1817f6fcd5168840d06df0ddcde10a0a0d9efe80f287d30120af3bb9b959ab0e09239fbac4ca8c2e2236f5f8dd2b62bbbd04aad675f3198e22fd4c981a941688ab42b4d1c88ac4603f0273328acad7be00aaaa085c3e8e80128f2a1a353b8a37914fb4cc9e0780d80c118a302c20f0b6766ab0b43f73372f208c8173730fb8726f37a99388b6acd19ca382750da6c927a32df8a55e9b09d12e0f74214c241d97e67df0d6cd4e7e614ac19bb7f95a51c67a0b1e7161d90efbafce0113a35ef9d33312a0bd727569bd112d3c41ffca1f2e6142001bf87cadb4bf0f6454dc8a8e8a63e25189ef9fb7394da850b0e06b4a3987ab41ee3f3ecda718298d8286ef1a971634399a009e8be0dd214aa328377e30508ab0fee9a3ecaf61a3dd8dd760c0ab403d0003d52f8a600062aac25f65110971be839eab781324f66d86ef04a92adc2e84b142eabe05c7520ffad6fb54cf8d941d2686e53fd16bb3aba8133000b338b2b3e40eea7aa985ee328944bfbb31a0a940ef8b825db2aa19d444090b8f0b76adefd47335c837841afe67a888fad8519453997859bea6a9d2832b641f4a2667284b430f4ba3c897c6c66b8ee8879d06cecd4d6ca58fe8ede09365f78a23dd664f4caaf7c13f01203cee7dbaa1686a172f5d6c89194be5d4a99d495cc5554226223a977bc62b4f3242b4a487e2a94d2b86323a533a57eca13283cf5fb7f3071ac8561195681bc249a45260d790cdc3fffd9c10e01026a226a36e0444d48e9baef985c774f79454c10761c247f2009387b0fbb51a5f09fed190fcdc7791086a65ad23637aaf5e6224c9aa9c1290b00b183cc905f09e8a22fd15be782477f67f5e5ee330f602cb7e420b702f2c8ba6e02dc857218031662363df7f76de0cd7dc988b944b3ac3836cc8c2955cc3e3b42771a98ada9926540b6ccd4259b0531004e23dcd00e1974dbec34d4a13956342bd011c10ebfc7d2280388397579a2d91a235d76053d2dfcf1e195910ce03c11b21c9ad8a72be37a0494aa4ff1b9c3013559ce3063b246f3e6eb68cd0e9aa3be7bf4dcade6eeac91a375f9956cee4baf904b24ec03df5cdcf4bed6ffd64125c388ec7190a04d2c2151dd1b9fe3a4f865919105c6e76b6f49ca64e871edcc7313582c97b017f9219a7bf9f72eadcd3436805b7ce472fb74179f2222ff4fb0abdbb505b7ad6583db35de1185d4fb55b88d4f5d06c93e0264ac0b523559cdabb64e717f099f1a5eb652acf376f36321abf23c94b9ee22b0c66acaf3e05165e6fe01e448f0e01af3162a2de28027daab0eaaeaee1c086a11c4762750be177e36ff73ce40dfc3a1205963326937e21ee965f18b4957edb75c0e96181a76384e11aa808f103fe30738ab8efc85489125a162a38e869a93f14a1e9be633db3a3ff838583b45d0d24a686487a492bd8697e30537692518ffc753e580e6976a0d7550d972639cfb26c3c0ab5288dfb4d4f9067a19e6c620bb5183947df72137b908f7aeba17cfae83c5b507d22007e1ab7d3c445c15c2ab7506b30087dee07ad8477e48ddac4d6f847040914298521022df82f2cbbf81b75761e9a6ff1d7aa53296d2343273c8d7ea470f2248e15ed48dc431018aed2ff40b09dceb34f941586722615c5141b7837493daa3a74e478a13d26c321bcf09d7abf8c978859c70555840ca0aac4839a18b5b9f521f7796ba3593bbc5fc324a23c35cc262b3a59c7402cb958064049500eab16e1a2901020ebd2a1e3f37bd66f51a01e3e79545e66bfe322d1f88a484e4c7d58b87dea0f69a54ef9e15f227f32dd0fbaa6d21d8e328314ce6d612bdd785904b9f604979b268ac087f7879579602e8e06a3c9f852cdab5771adc0497dc810d2ae1f5308790ab4f043652b7b5c7b5dcc7fe3bfa0604271ec226993a176e976746f3587eb86e1e21e583562405042f0548907d629a2ab7f1c9ada7717720b830f1c0219b3b3682c25396bb27682c56e4016763e8cf98e0b17e7cee9b25ec716924fca3a4588579dfdefaa208f6ed10d341ec10d60b2dc93451cb79e2be27f307b1a25eb11c463b8ed910d11fe811893bc8e938f3446ab80d5b1505bf0072ae62c4f53b91a0cd3cb1df4724821d85a2f47230dcfe415c3c49a7b4c54faf6c1aa31adbdf843cf2963b51916e72b342af5c443b6127033ce883ba3e206579d167662c7f73275c4aa28033580d156718d419ad60b9e64dc2d8db334481596d134521c352b4d9b8b6c3a3717a1e10495a75230f6583fd2db04e049bcdf2022a0ce500a5b69b4ceb6414b47ea68670d1a2cc13b003216a263e603d0b1cb103ea74d67b553060d1a8039192aa8e038f855465e0930a8c75cc62287a1ebd7c86cf74c5f7716c7fce2c1e6dd8f89df9830820d85d5deebafb0a5dfc2286b87ed1e7d5073766284ac934feff890033426964efbdb7945bca94a40c6907f407c607d6e24dcbba8f488eda47d89ef6decf39d22e58bbc06dc341e01519ab00bc226b58629955d12ef25fe0afaae0cfa6e06f8482bf3fc1b05d3c3fc25fc9f31f96e7bfccb505cc1e0ed534f9a3a79e02935827c14a3a4909e6ba3a531f942569527f96bde4ca96b2f44c94761c6465afccb5058bfd97b972127a92f8f3e477f0f79cd68ee4cd8a6edbea6f749ba99893a2491473282c6cfc8f43e5766549b25737646539252b4b0eab04c9061faeb4dc04bff89271d37f719561acc9f08b36197e84895f120281a05db624dd86dea2916881c591d61144c7b87af816264337c5168c17efa686a97634fa13fcbd37c29f5732f95a6d087f36762bca7cf0b723f41efc9540dfc19fe7e1b438716cb909ba4cfcd89adf8e10fe4a20fc791ffc7dad5f8d10df18638c31460c48afe2d7da303b76944a106a300dd3300d5387ec0f4dd0f1d6c846240c9142beb108d06b75116a45a8c2f630be800dda431fe43600f4fc3b0b44820071647f5880fc1e0be4cea011156290c5a113d2617386442295962821bae64bfc0581ae243730ed41d70dacfc892b8e4560a02bcf095dd1e5312513c81eca72b6fb94234f089a4a2a5c9d199c4d830dae7cb67b4e695d208567b0f1dbf306c2ca8d9b5cf033ac5cbb8462c7649793e28fa22bbb82848284b2ec5ad995a3ab5fb7934461e17fed7a4892fdf0a3cb47236be3c3f696cb2c46a3d82e679470b091a38db2cd823ab5665a848dcd0e673339b7dfb2b0f15bd3b2124f9679eae743638c5f6d5699b6555028d3ac9c98945e53d2bdb0b21ad86f25b7899494ae2431792591326eaa28d44b4569212671b988e8b2d028ee94bbdfc29c88d8b28561c1f4f7075472e2282229ec8843e1ac671f1b4b9486051b7f663fe7d794ee654614945a868dba1798b58d8b306623ce67604f60da45c21ef3a594f26327a54c8c287fa2ab8c4cee6f540c50ed327d061adce57256a9e9f83cf47caee74258675625949c86e577a3a423ef80ab0ee7e52c01597b48ca7edb368faf2c7b7138beea2b5b226bda8d59ae74eb32cc71664b6fad61ff75370c759f799d48eabaeea57e7704cd1c2cb52eb42bc45ce7cce607f28cd0ab329bb10bf78de33a4e7428b1171a19c3f105832e1a26bee2cb5d9ce69c4083231e1607c903af8dd9ad60e39c73ca68adb51986557ae2c9ba8de3c1dd6dca8a7d49c319ae18ab18ce4ea6cf15067448c43c7fce3cff6b29fd618b7cda19d179621ef06853e9dc5d39c968280077f427bc2b5813b70e779c7cbb97f9a552e9721ca8655d520419771f32430d0bd883f3fe03cabdbf9cdf7d471f5af556b6d9b80bb374b789526b4dcd4672ae4316196173e8c5a0279fbb1af4e4d7cb8124f99b16069892e5b70924c997d1006dcb5203d929a5d8463b6b31d30e78371f9b30cb99ecb9bbdd0dd43cb5ce316bd7618bfc7967e68124f99a8d9b4e204942d8f2692d195936a06611b6739ea04e3bc4f988a4bad25a6be460b3dd43d1878ff6311fbe8c51b3d16cda9f68e9e8636a62e868d26c22a9bf104d145586ac5521fae0c860de19a18eb99c705277c95d22e1e071e2b919560aafc8b309d93f6a0fb111873f2b276d13adf0b34a670f7122d36915da69c53a1da7c3e966c967bc237853a552a9e65d65352c1575aa52a9547473395518571baee4d6b94ad5c15efee7d5ff6e7c25940c3f196a3fb88ffdd5ce57a954f701796ad8e38f0896b51543b0b1535c1cfaa79454bacc6c73811e7c38ca94898c592b2463159268a54e4cc16101ab90a1829746279e15d78484a429d87e9ae7c460add68e46ff9e57da91aa59ad562b89bd56d241927c912504b2dbd921412746b10f8d5a0ad97b0549ee321fc2944afdecf613a0299eba0ad96bad118afc85a8883232bd0429d8f8d39bebe2a449a964a60c86c96032988cc424c699df2ddb84868132b63b4a9389281d4f8d1d90fd2395384296494d309ee2a96631067014043b136df003b26851f010fcd1b1060a5e9537d93b452351cc86c1e410db61fc4602a19c91faa80fa58c3e2afed8d2dff425d296a24e117d7414b0a5bf8adc54f40c7e42e8ddaa46350ab2f457929432aec4ee955150a8f61acae84d6736ef4ec413b248cc03b9e17429bdbba9402bf458a0eb32903dcb26f4e4d48ed838272631eadd3d822c5cb0f1db25ce2d366f8cc70d080001e4fe582104027a3c8ac83d83b264f9f2880e894ec66467c4ccd25d9aa063bb9c18ad99b6719decc3409442ee27d81cbb2eaa3af5433b265611539dce0809c240e044114e176160a0883111c57533f144458c34a0d06c42c80dc244c9ca97c993b844ccc43112df23352c27e4af639cc09af9c18004b4d73f9213cb4eede3764cc740962b6cd7712a9ed665597370c0b51d3d1d8d744cf9634580016cf5a566a1e79c190726f4e4c49cb375baa4ff19b46efa31c48f958d0fc411d971404f7e762f24c9af577ee32840feff0764d1e567432b23b9f2dcd74ab13a868d4a894d396586d18965124e778879bfe7de137afe81493b233a1c19271dc106ddd40f7f7353064973661c0042c487c48e2e70e8cdf9d2810dae7cb08f70108b33c030c02d94ac103af1fc773f201e197e08f4f16c18b6862c6190fda310b9fb12fd91b5b5661b08e02e0d1a0ac8183ba03fdbb41a22952aa54aa952aa157c1bdfa8c22b2b5864850c2c52a9f09dfff1f1fd18f713d1e47e189d56abd302b94427f02b462050a7f5a1d48f3ca0942804b9bf2352953a4ea5427943eecf54b9bfaa40a915c67420810da02e144f11268a209ae4eb156166919b9b1b900ab4b09ba72677d5aa2ad624449364551512c8b2062eb8e0a235532090063204b691188dd846f5c98da0daa57340adc8f22912a0cb0f202f9faa608f205e368d9430d034575d805ebf7b01ba4c2dda3bb929002fc44b1e2fdf6fdcd4e32500dcf4c3cb1d2f5d5e4ad34b1ffebb91e543f8ade878f92ad0545b5e7e843d7ce0c82fdfba2907102f31ee537ba83258acb34cbb6431dd39802e590aa0d73f576ee2689cd49caabd2e40174e09d02bcd15b74292fbabcb4d1d1b27350bfeaa0fd8b56d2d1725c78dae9b9b8671527cbd5aee496c6ddd4cb4618da0cb8bc8a6e59a742db784d3bde0c05aa8e245a4320213a59210d140ab854d7bb6e582562a27f50d13931b2727275b006e0422c48d2c27c59a1608c4000d2425d5e974acc7b6dc4f16a5443434687c8d504c080674036a816c402cd0ca49317ae82186f72942b23236a63d1b366c00b931e53391a6636140359dbf6ff38d2b6bbb99a852793c9e0fe8d3723dd9f3f97c4021e9b2f2ce6419d48c199f895eae148dcc092569cbb5b9c80f3f7c90844a422db793a29139a1200bc62f438b15170485422fad1250cb0464235df63959de99fc406e8acc8f9b820a227f96822c4645e4ba01c015d138a9655031279a172f6094601103740362fd7fbed6c6341016e65a98962964422db7fbf13dae2825a211a1443290e58789c9b7a804497b3dfaaf0381725c908d934e4e4e40fd4204e08a7eb8a2168da7d09820c9fd26dd0ba8d59ee4c2a2fc1647113a0724da0010040e1951229b928e88ce229b9689c8862b29791e37c238e162f2c38d27936e26c6c49896bb7db6008d725c51eb26140a897e68b959c6464cdc3431ea84b85a6ecd382e033a9b964b3386225170a0e4b83480b45c0cc4fa94ee05c44ac97153ba99524a7784671fef838f1b218b0f9fa2c24997fd3a2e2eecec7153649cd4cf23c6e5a69c208b85699212b6efe7549b0d87c5ab93a449386ec7d51e6c1387c5051bdfc64d39be3f4506f66801b15a30d971f5ab742f2d57e2b820d64d41390983b46852fd8f5be57ed33d41822467ff752fd1ab354d3bc981453698cb49f7225f742f308a8819c46aafe57a9677e687cf7141405c904d7b3f7cc7a675644710d52ab2e98890790b3fc068b91da3e5c66f99c9f1580e2c42d2a4fedbbde0c0221b914d8ac8a42425044a69791f4a387ecb8590c587ee8505cb1bf713d57c3e051b1606e6eb981af70b9d3e110f72ff0c91cde7c5e0fbf9142eeb7b18f7c5fdfc8afc81589f22b2f9ec172a89402cd10d724fe113814436a7fc896c4e6872bfb5b130a213d697c282dcaf896cf227b2e998fc896c3e2ef7a98db48bfc482bed8e49690df112d6a38b9637ed7262b4661c87db9870d2cbcc124e38a985743a3b06db192003d21d2009968da7fb0cf163f5b921ad5b50178a309cae7b459896178a4093bcf15a536bc45057b0c77cc7b5a6d6f88dbc29c9c3eb0e23c81d61224c84e9566033972ff90a03edba99d14834ea90b5a393285f486a4d87124d106146004db5a626a6e0a521b135af9a97162faee3705bc789a7cf1436b8f2713236f683af7639315a338dbb1a18ec27fbab4ab2b61c715541165694f70049482d029bac04686f001d97547643fcb09b07eb18226ae4aa6a4ffb82dc406b110e5840970420a93fc65891fb834093132d599225595e60c548560c9c709364c1976449566e1b0b925d902c990534c5180986aab22a1528da6a45933c27cd7c7684502854d22aa351494989490c596b32dfa47b9952041daa5455a575a15ab17a715c5555b571329e19941cbac9e218b5802f591616ca8f8d8231fe166f8a1119e208596447660833111939b0c18ff105ff8b2f777dc0bddba3477f837bf4e8def81b12933b3aaabd081a79e28e71f78eb1bd040ea1c31515d94e83cd031b5c8110ba436d933f3f0852d571a36212922aad4d646c6bdb74e5e168e4ff25c743a4010d4cf673a48934803d3a76737cd23c0d64d1e0202169724dc88f52b647e1a1cc61f4e1874698376a6f4ec415b26cbfd58fdbe64486a590f6fa873047b047cf2a0437a1b51f61832b308903b4d75cbbd89921b108901fc4e7381b80d08f5e5b0275591add03c824b40444a04d4b74919df38f8322cc8dec3a4ae091b8e25c25482c928024e260b1220e106144d8963ca8548232aebc7f09cee31d4e771417c9de45a61f21dc22bb1413ae70f86340a60f3dff49b5240e90802c16c962914c71bd71004f524a29ac1092e4679b02c48a0de3af17172cecee88e8b6d0f425613a2d578eef1d115bee685a58f85fa795a3842056910dc21ed88457c4b883c78763cef74c64465fc2139600afd8b1a3547242c69800579e93b041d803c20c9e783963f2664aeb68042be6b223c426d691b9ef044a92052593bfe3ffff5214c106b324edb5a669a1efee25f49095a5cc41e60aac895c718eb4376360b712901f7812a52ca1166f90d2089a6ae871444554cc88d6288cd0131d4e982952d1a4fe92177d4c6927a6a87a297ba51ac91a27b5be9ea25d382fb1f6188e34da8da93958edbf4813a950c9d409c61c7fb68b359ec535f2a68bdcdf11d1ee8583b32a521c76fc8d307ce3260ee5a4ec69f712045e9137d87177a6728e7056cea9e191258e2c4959de2c4fb2f4649965c9a9e1ac343970569c236e5a791831fe39fcfdc59c8c1d3b70a9743defff638c463002df06306799b2bba58c953fa3b5de506c34f0afbeda45fa7db9a963621b91c2690cdc3d468f71bebc8ed12068fc9a45faeed45d888e520635fa12226406159b436c52babb4f29a92fe158ed8ea8989c32dbb810d7711da7d649399d4d06be4561bd636374cc5f12c1a63be6dbab080c1451441130c21b98dcb53427366f47c8447b1da4bdfe49843ffdf7f29c6fdbc47525ef9d60e57f23956faf076031a7e220dd65427e44844039cc0fece1b9a95708132f5bff833741aa19f2176de490fba38d9b7a34b2d62b664bfe1b99fcf7a3ff4aa392c92db92190c438d242fb1bed3eefb9327f68f762576eea5a57d7f3165b6b4f4bca966cc91636e2b3fd8deb085d727a88e746c8c2f9dabdd8df328ec51f11ce24c244bb74df1f4408e7651704dee4dad50ac09b3cb9291f7a73005b8d366b26466d7ea4f298972a50ca12f753229eeeea203b4977927824f66ff1561a5f6662ee0c8687c02b80fc60caf797316221a1aba14bc6221d8b6cd1db9dd24c624ee891c34686d83b029f108f5878459e32fbd8ed799e2733c9d29ee7e5272ce1e61aabe779d0095932213bce9265b6bb3612c4577c499444dddc44d1022d5eaf4d6e2e1bfa6ac1c4dcb0e88d4f0907abfd909466d5fea8937012cd49b092608d2a66aded4ca31b64c9d09b9b8d9b5c9744122cb79e8ee3cc988a5a1eb6c075ce2898810bb6c0bad80fb8faa1326aea93528f052c85d89494560a21a5b28b0dae7cf4e4355ef34de1aaa6d6346d2a6cb05d4e4622930c1fa5244348923204fa786c87d3719b46532936a57744c9f03794141409c5c9c6df6afc66fdb8a0d6ed27903dfd0d1be1a0c8fe57890844fba84403d1ba957020da6fced1ebee4a48209a94522a31816873ce3995c080d08b61188661b5538202d13e2cb01f95b96961a9a679b956aa191361a84465da6f1a7d9fd1b011d9d32f22c33690a500191119fe28c65efeb7aa6b31a0ac95779b166635a4d75d271b534304cdee822cfd5a1ae8ad4eea19186d46ee6a4f43838d4f5bb25d081c06b856f62dfcc65b70fa943654858676a198aa54b95f45553e07da7257741764c982bb68eba6633bec8f79d8e0ca0723957dd220da7319cc0961ecb863074acc2a2e4740cf07d09ecfa8f1e22564d164294f246ff95f18315e7a173985c6c42fe32556f91d2af7875606aba2827f0ca08f20797883624bb99d6ba46846af9dfeb3aae1dce06bf212c1505ab32ab32cd3362de5ce3ce39aa852167582713f35524a94234df2dfb6ad7b91f883457b1f564d129f95935c725c29976618f753c3128944265d34c953b00846e55fe02f8848538395d20d19fb0f6525310ce654c11f1764c9c214c16cddcbd4dc95e24ac13a4a251a3468a408b929d5899f066820263564e0383739e56259c69d5979d826941567c63579714d2818a80de843291a500c8c3fcaca4d25252befff49c11e29ef1cbe1ee7ee2aa3917b3731ca2a84b24259599b82a1ac304ea76339299c9b4f92cec765f2ba31797d5c6e8af1fe262ad8432506367999bc543a1d9b72639671f1e5dc38a9fadf0bfa0b427d5e2e6b33e72469cf41379c9bf61c06feb8502f5eaae00f0439e5e34f4944e78f4b6b7d5c293365e693fb791ee1cf8407d95fc4b9019d402a932964c7227f1b14ab0f24f3990821fb733826afbcdd4fe60f6595fdb5fb81501f1788267392647fece3da11c48f39533d641249a1318ab07da8607f3491185fd4c8343206342ee08fe95242d8a5ee77b40b87fd658c9b40a1970f579c92972f638d5c74c13c2f7f84b99fb8b4717787cb72ee1be736a554665926b95349bec1eeb834b7818a8a7292cc6ff662984571cfc15fe76463dc60b1ff6c4cb650a421d3e7e27bf712b185a23d47cd17703719e39cc3dc09b2b88d691728dac5bebf3df9d6bd74346bfde686ff5652e2b140c9b590454aae224133c7813a22b8acb581ab28cec58e64ada2daebe093013220efee21db9e7b87611cc6e9743a9cebd973b993934eed65d1e958adab282e2caa5da0a33a036440bc4a21d39ebfed5e3ab8a2da7394c763dfd3bd58293b2f39f53f490587e24e4e72ce0887ea60ee94c5a77238cf995b4555d42739ca9d4a3a76445496534a5408061483957443a795c2f103cb67c16a29d9e8c1871592f772da78335efee31b3272d4781a3960461023c36a172e950574e188f09c6adab0f045a9b18257565223cf582a4f9552e16bd2e15bc2059511d429a60a5597c21724837252c7b036867f582d370229e1960b819c3a9d8ef5d88fe8248a41414901dd805aa01ad00aa402a5481724e3a41218304a542c4ce7e6c58b1f3a9d969b6a7c3f8806f6f0bedfaabc1cd1e3f17cf0f5783e9f4f086471dc1498d7c9c9571b96935a8608a294688b0f08040aa952297c3ba718118c89cbe42512fd88a54a516a0528140aad4a5626aa92544ac5f9e1a6c0a0bc583e1b41060362d5f870453d5c918989894b26142aa949755da7d5b969203a2d934eabd3c2325429950adf0ec7f7704527518cc94b0483c35a0f8e191764b302a93e9f2c26f7975aaec846b492c932192b5654954af980452a158b0c554aa55271a44ee76dd4f04c40a994b782efc669b96855e31b4ba4526119f8d62c03cbc017ab714720a4c6a7d0b8716fdc397bb829366ebc8be2822c1c11b894f6bdfdc775b668524da7d55e3710fd1d562aa572d30a0cec81bbe756302895c22d7ca58c0b225d9497931a54459354221bd1ca49ed19ab0616a9549e2aa552a552ede1eb352e88c605a99cd4df61b9cf48b929ef1fba91bb446659bc512a899dcb92c492867221693c9fd0c85d8aae9cad1493341b126c54599f81fdd1bfa96cfc6dc4c176a9323107725239b74efb786c9649e89a67184e4ae5ac5cc7c93c279895f3b569d90bc3a6dc382a67e53a8e639b6f50c3fc0836c326f4b2ec035db6695cb669598589af49398e4929657c613f8083cb895123d852a924adb536abb566b462b314e33b5e429bb587b4609de59cd89473ca1ed222235631c975ae6913d3b49698e4b889715ca772ba17df3a5d013cd71ed2b158e5944a25897d1479816e45b0f13bb5c3380edd324e9db4665b15b3332936e9fc6e7e369f9b73cedfb0f92e29463be0d09b8f754648ceedbc4dcab931d30e38f6148359ce68cf61f43a6c999fcd39e7bb573a9fa09362d8639863aed96836eefe444bcb193722582efae8d280d1494b7e330947863c728c9fb9845d2f6d1ab74cdbb48c624f9d6a2127462be77694d6f76a10c48e1dcec5ffee8c3e552a956ad33ad9aa283fbbbdc0f69adb54aa8de35439b30f8ac669916275db549b6a53d15ae7f683ae0d736273f41edfddb1b90da154338fcb8949b809a1d65a5dbec3ee2bc973becbf7988139e99c316231468f734b599f344e1a27c5fe0a4d63c4300c9bef4e69ad41089263dfc1fa47772937206052fa8ca53bd87e7086cdc54e977362b2c65865ac71627262b03dda4e679c52a26a1362ddc1366707f3008b4fe971cad8365bbbc7021df4649701ee6619e68e372a6c9c149318f5da9366d1cee670dba66538243b886198d3246c73fa9c1d57bc1b3b4627ce83471140d4391d7bd818f60197369b0fb61e6c3ca8d6c62d6c345b14d663810c92a40f8944e490e8f106b3b119e7131b5cf9e2c925cdb08e931e4ec77e3c327ccfb597e3ee3e471db68180ec34a027692800d317025db4318ab59c18ddaab669f54209eb8d2d0a5a67269b58c932ad099591b675c8ce8d6ba2492eeed4724839c7b9bbd7c75625bf417b7f8bf7a391f6f08c90cecec62d3e259ab9867115c7544a26739f72ba74a755b4e733a9cd064784e7657c87cabe7aa93b75a80ec5725397c2198e32b2eec5be6c171b1f7fb3fd37ed92653346cacecbeced6fd98d37b195fd175b5b64237c877821feb33ffe1be5ff1ec87f9e001e42d310570017c8cdf7c715e24afa9e713ed9a6759fef5c993f9bcb4d8d42b9502e57a73bf91d140a85c20ec89c4e277362f7b2d17fcac9baffd1d5c61b1bb37bb118bcb1dd4d87b910cd682a75471dbe20b94467c4cbc0323ab348a9a7c654156d8a472291bcf21f6b26667d3a9c0dd4bad4631b353fc371d55ed7cc3f126b22cb4d72255912b4715a9c56a7f569fd73ba178b332d60f0f80efe4a3d7c04f11bfe4600f80c0740ae6cac389cae73cd68bfe9e07646eecb7659f9f8db063b148fec38b293b2df134ff6ac4bf945dddb9dba5367a44bb9e9e5fb41ff79cfdbef7cf79cef5c6e7ac1100e812124951eba4900184252cb433701c13e3c7453c61092581ebae907bef1d04d42e01eb00d49ffdeeed41969af00321edf88b1dc8ea8df9d3a231d6a055f19538ed8dedf255619b5d792a6dae57e7fa645bbe0f83eb5c966a2e3bf5136d1440f5b645376341a3d6c8fb4d28d32ca282619b829102e5bca49bdb19cd42e5f04000600600401c3078c1e30623c0ffc95328c87d1b97660e37fdd2907feea0fa91a5dca4d9d8d07e1af7ef0676f58fc7d077f5ecb7738c5e9525c8df748ac15566e8e35037f9506feec0e7c721397c2f8abf865e0cf9a526ee24e2ef8ab406ca98f76da5c4e6a1d1a853d59d2316b8a27902011236fdffdd0e5e870745de4892eba12fe76d06fc15fc907fc792cf8fb1b9dab87ce65a373c52da4e05cdbf624fc8d3cfcd9af8139d7144390702c1aac19ac1556912eb8940c8c31884bc12da4e04e1feee4c1dc893b42c48a6d73b95618c0b9171a21b3c4f22fcc313a572ab572046e51648a2d8a947071d52e47da657eccb22cf4f36708af74dddf19ed6b14b6a56852d39669973941fe718f5bef38e7d453cee9def17c4ca651f3bf46b51433054a7d529e944d75525c8aa6382b389bc7a3bda7bbc0cb9671b88ed3f084a249fd364607b6761ad552c8500ceb4ee7454e4ac79048a44a931a224bf41b2e7b9011f6b840ccfe367c9bc24e8c5431ead15aa36634326d86b6ad6c9c0caec31de74a4ee72d8d31e2f8d67a60783e2f3e2095ea440d95a094989c988846a2916874627282528292124a5101a9bcf8bc80e18111c3c6f8ce94f02f87abb8c339b0b03d199c8c956d658636834646a346ade1518f84916c4c1b3dc81e6ef80d9666f1214e09b17f6107cad195f6dadda5949493b53aa60fafcc302ab7f7f8bebdfb16df37ff6e8b33dccb95266dbf79dbb6492a39e72491ee88fadf2e746e9452c7a84fda2e38a1372726bb3bba6212975fdbd1e5a47ee1c04a3cb130e7699ebab98e991dd3314ee3a679f2989a3aa95c7e72f5f78d9b24ab9bc64d92c57a752b6573ea538d536fb98db362625c3165a80112f3344f5734c1e58a37183206d66864ad8760481e523245650a92c106f0244f5734c15d94ba8bbacb856d71f0ed0636c6226c36b0c126b3c96c3690dedede7346cf580012b0bd574e3cd87fd98c05fc087f16eb886121a074ab0186490fc4ae1988025942964f05b2ab452de2a60fa854ed391539543400005000c315000020100a874422c17038d08339d60314001264944682743c1388490c8328850c42860003000100200232333412016f1448531554470ef4771e1f44fce23b4a68bd3af1cc6dc9f62c005e0ccea3e5e0ee12de459cd8aa646605f05b7c1a66a87c52efc7b3443a7428750fa2bd2f524e1ddae7e8b4767d6c66eb69999607f8afb045ad649089b54ef4671540c648c0140a2933f8c0e8a5f0c4f181270156e5cee34f0312e72a62b2afdcd96b1fa5623c488ed7ef2e915bdef53b44364c49f5d89e699d07b20193f4fc2edec35a64a67ba095e555f83e9deadec28c41fa5425c65b6c0fa70cfcd5d97e1e0358b880310d91aa9d176a8d3ede875156edb40e793dd2c3a3b8e4e63f6c200969f622a5d7468ed71e865e056fc52cdf038c9515c494a3531b0af189a324fa002e5e458a464638eeca492376ddc6155eb38d110daf35405bcc0eef20c9e43bc10c953e22ea66c2c4af524639fc1b03ed6224ffbdd75034dadf3570c4aee4e6acb7d23e966a80ab29037b5788084af381266e06539242e074012922589f1940cde73d025d6b77ee8ad59f77753288487813757b4575da40bd550b5aae3e12a8a782bb2be00322755f3f8eb435bd098363b8abe0c20c0e408ac89a30663823d28db9ac5ffbf58257343620f8242f08639ab182ec8a3303820062a20e5bc8625a1eddc3ae18a5531b990019bfb0e930958aa61ac9ab6b8015539613b8c82f9c1e536038668961de655472649e2bdb66f53fab363ba169cccf287b3cd43b50da8dff8c450371026b04288693e8627da9cf59e5e9dfa43eb7f03cb4367ea7c9b0ccf42f6f50774110bf5ada15d6b49d4671a4e4ec4e0948ca96e3e9da9592ec84e8a6966672add17a5432c9359633e4be58b640759fd7757dcfc38f2d4b3e9280d13929f44d665aafa493d49ddcedc00f418b5a83e12a39b444b4e8c608bee00a7b0f7085069d52563897d03827dc19a16f7dbb144cbf5a62f6d683dd03604dc1381ee8c06e3cba44a4c694504f5815deb23f93629aca915da5803c1f16540b5dad67d0f51c9ccd005fe07934444eb5d75077d73ed4984373d93aab2619c30c692cf2e29a0b1f9f4dd81879c6719767fa9f1e62457c71242cccb3c4981d45c8321aaff72b6fce36e2780d7d1ba5141a40b71724ebf0a9321d82c1ff6cc567369b919e473bbfb9546c1b396420f99085f1ae0a74d875c6875f175e490a9c4f3de3de620353885e1fa3ce5f94900a29949992ad5865a1c2170040b255dcaaf52ebed46db40fe0935f0fe5d1dfccd07a50cc14cd4211052e09135fb99b64eb446a09f1fe8f1250e89bfb4ab8f55b73003c67d3a3194483c0056308c650c956e7e04bbb564e8b2eb0d293cf338e250dc64c0859e66d26d9ba86e4af579d1f23441f245be3d07e3bae82c8797ced40b1b257093ea40d885941f5214f6dcd6bdde9b05cf26e609b4dcc13cfc5ea2f7f2d48c0397eb5e29405b9105b6bbd63672f0e034b2015140cb03090fabfd0ed0b196a61d5890074732d40d363d804bf0128f4ea344a9fc918d0086a244f9d9cc6859e4874a9682a53ab9de5b3d064b16181c117a05aebfc30dd706be0d69468d9f25f6dd49ab669332200851f1158ebd168f7de9a8b3d7cb9ca603b939e4fe8f9aa51229cc2a99db6e3d0224fd6659f972f4f5db613588c9f743e77e6a63ea469ff86007fadfb834b7c0953aba2c8b17da4b17456461ad801e150eb830593aee1e4177e0ad9567d61870a4642e4f7a6d523d33a91a3b0958aa78ceb9da7c80292502232ad30696d2bd6cf4b6b1053926e111588c30d3378ce281b270eae1c194d6a28621765b952930556c6f407eb18d63ae9ec64d28146d5c509a887d1de977a691498d396d20169fdc5c156a245ebb17104195a872092323892d91c089dfeacb6e13cd35ba1e018e6fee41dabce45c7d76f2b58cf206fe83b0da2f7d8a3cc97fad3487efc58088e9dc7b55e706f73a1f4c9b3de7d4930d9c6f6d22c9c283e6af100b259553933b60ba0556273d62e29cd0b418337bacdcc0ccab58f579ce4563765568f33ab5664865f20bc5a1a8c8af60625c371b0f40a8636be692ee710358bc275b6e7f4d2acd250bf0d26d2b366d65f241d553c5164394cb16a5d8697733ee7bb0bddcaac6b70b95fbba7b20f1fbe87256f142896d54a993587426bf15b13e83850b5b202a991d5391f1d6086af8f8b28caac1256356217b47e1be1f82653423b07f4936256d17e29d65c025a994364adacaf3f2d64ad45e534364cb0987552bea790cd65ab194a6f868e192d409cf7d42d306b1baf71aafb667ccc2ab3d5187a19f09c09fd7c306eaeedb99d6f5b1551179fb601175b7a05af6190eaca4725e790eea7d9946e616c97ba4593a4c1ccfbf90fbf31ffa783184aa9373697313640c6f0e0b590ab5d1ac5622dd4ddc4a40c8061e810731c3fca1dea0c98150ee89dc7f5615323016fa689d5be7759112e38268872d502d0aae9a0f0f8a6bacc226204d654732e6ba005684071933c8c37bd312375f019fb6f599d6a1e1530458cabe91649ac68357e9e5016e91537084f128eddbe6efe6207183c2aabd972cb3af3a41157dac002db21c3cbd90155d67941085796a6775edf0f1ba28b0d30fd222d7fe70f91dfc70bcfcca3cc534703b494094323d0dd155931750080070af4dea77e2204fd1ab27e1edae8fde71eab0b5a7f21513143ca67b1ebf780aceb000682848f39568e47ee02ca743c09ea880455b5402964bf38ff271600d06275a8f174b146a905f857ac956b398a811a7fc7df6d6762fecbe02a728e7acf7d97471fe0c5f3748e0509b4af89cd9b6c2e956744b26dcb008c6f78ffc2c13cb26a645713c4b13ee16f446376b10c50e53a3ef331c95aaced844b213455af6b7b9803d6b9ccf7ba3544f4f449990c75dea89a656dce641e180d3a1bfefd572522486f29c3b7ae0c1f096718c13bc879c8eddfdf701bfb4857c10b5c903a70bbe62fff869b984205000f92d7f05889982af4535cb314fce558ffc55c9ae31cccb70f759f4bd457b3f4a2fcdae5ec2b9fd8b40883583297edd5407d117674c1da54eaab6f678699298303e78b4236b5455f5d5f881a3ab479896b35cb00af42a1af7a631d39cdcd68048677fafe4869a2a733986d11d1da1cbb14bbec47acfac9ccbf68c8ebcabb62eeea8ebbab52dddb2c46d489532c14b2771f95edcb9b72c9fc95e31ce08a586a2d24607eb743620dd7f8826657d1ff8b79d70fd7cc4ccc677474cfe5cb7674ba5799658a7107fec2bb840da9ef13a6c9f14c0edeada41c4a4338b1833cb51c161ba68d7863206b7bf27d027a0c4126e85ed1eaf702cd9f71d6bc346df259386e1f640acfb4e2514edc3f7a70c410210947970ddef6ed9dd2f286a610569b8b8c5b7bbe9904c7102b96e28248aa594fcb91c42a96933c34d698be95e529f7206487f9bf5561a078587ba6d9900be958ccddf51e2f6463d80d1fdf314c96fa64d3cba5c70ead7c354fde7d733a491efa8dcc6f69e46cf42a532850d99775722a82555127b997c4a00b2f2b0a33b0a031bd040391af916af9337ace29b5d86c8a70bd420f88dcc832f9a7e84e993974f0a3cc9f3b8cdc481de25e1c1d1cb9597587cfcc75c2ecd1de703837151c44ef780191edd03ba5322fc61e66bc3d61194471ce64c601653dacf746922087332f01e315616f81c3181409c9aad15e1cde4c6e806782cf70a03bdd4c95d215b40ca7d9d0cb11d2f467a905828adfabba184edef292f831eeaaa2ea11d1c31a3d031ca52634666c0dbb2fdbad2aeec844649373fec17484aaa868500cf7a3aa11b09784d4507792f9d3d406e642b36f2bb645c6bf1e5595e6ef3d46b25da0def795f39ef0e6515efbcb3fc44f32e744a672038893aa962f731db6f4e32dd0111134f213c281e341c39160901ff72589c566c8852f0920a74673ab0eb6d7ec1368476e9c941b943a15e93bc474f267089d140adb9c355058ca1d651d8b4d78344fe25da77477b74304063abea490422ba7dae7ba5469220edd4c9d6a23098d03b0ffb6ab6326aec239114a04616c15ddb854c3c5a0c9e2041aa55170cf9c894169e1908aec418ab18e87acbcd9dab67a95a57329b08d5701afe34733fbc52b63913c110db8a319c729e515e141cb52154432869e392e244eb852b5184b27d8a249a218dd2082b5918782315baa3ae335df47202d45240dd69886135a3a01a587ab6613bc6fe904b73c77e3a75b77fb884eeec72bafa74ed2a54e826da955af131108e41a659de9d9c982398fe351637c6385ce93535794a565b277c659f752bb3cfc3c6c52aacf3592de61a22772d9be2522858f569ee24c70b00bd66e71935199d2751c43a646d95f3f63966d4c5170f0c4b1183959da99772ab7aa9fed002315124f65eea0980d0b9312d18c56fd64e074bd294799d5e18f24769617afd5fb9043425560482221381c67a6f2b1a2d00b0d72fb5718001d39e57c8916d5bbca04b6e6fd98e998699e30cb90b525887c36211f451d46c48e0f61b6fb3a15ede7b6f84d6f61cd19840fb42efba82c737c0665d2b0b3e59ccad2e25eabda749aa5c6c22c2166fd798fc34d7a62d08d4ff68bc7e244171fd2b578c9567c289ccab45b6fb5e205227d016bb5669a999dd33360cace216826451e6fc0493d36f003f946395af399e74c67935dcc4974f1de3d8aec0417df36720f22b3363e60f97c3e4291459672fcac2bb57f74e5261637d9f23b34a300b1418c80b00fddd46848d0f1cfa764e4b28ab6ff37023e9f856b3793344fef1536c9bb7fcbdc7335c098984e0a88e37f7c3ee1bd9322e1f3f171977b42ffbc3b323d3ff893f86e846d985368500797bb5791445c7e3da8abdb787490ff98d5553379dfa981bed23e031ba41cd98c71847183dfb59252789e7157fb5cbc83ecb2fc96f700d41daa4a619d7970ac428e6296d4fd0db73cd186d896c2cd032df3cbe010482417fbb1085483b19086796626f29af4d413e573dd6503f275d01b042bac8daea77ae155c3cb040d9e5750df027278b0be188a12423cc19aaa001cfa8c6e5ef3d30412d3b17700a53f9b73fe4cc85a3640a4b8f8ade3bdb4346640f6a7858acd0c48cd3a89844b8ffe8f30e4e9c2e0937bb0522771666ae3f807fbf8a4f59c720eb425b82ba468b4852b688841229372e4281c13b29901696af604523d88372a8d85bf0e6d4a92a600303ca5e2da7d06a4c649f8a5155979438b1116d1cd86d378b06785b0ea85f40f93954df4645a8c55b70e08afc600e7ff41ee3b3fb84e81e5889a0ebdb27fba47fd4a45f990bf5bc950572a56ec3a90e37202e1173e1ac836f368ac4393e6f4e7c9868916b468c1065946c7946977781141ca1e78ee53190422516b1ab2c6c8b0836915fcee358dcc2407736f5a83ddb94f573cfdc3e268ffc4bddcc84796807fe1d6db03821104420856aed1e5819c123e42be8620188e45ae837970fd13995e881c2d51040a6b0190296f0bd41355ab4004288da84f0992d06c69b00d27de67e3820a7a982ac2f9919e2b01e5caa76bd6ccfb5a01680802d686d06ffffe4cd66bae36ecb490d22048496119184fc87c7e9d41507d02f7aae0a061cc6bd7f5022d0afbe500eb8c18afd6e5008d1486f8de388b572b3f68d22b647f5a5b52ffe062c92d1811ec24e7a53220e1a2b86f2117c8764b2ad864419b1af96663fb602da82323743112f43a1c0bdf16a7a7f436199ca09d91289f633b78cc4bb3b354c4cdf4570951198984f5a5ef04260d4faa7f19651ee2bf6c3b42f85f465ee700303b054c883d6014697a2bbaa410da5ffc90581f3243c63196824497405429882e7a922f7255567a0928cee9871aad58e97c0baf985c60006bbed296ecaf163d2a1629ba9e2592bed94caac655d536ce4ba4c56737711b679397973808a3b0f0405f485effea1c4c6f418455151744e36ff0882ada6e1f585e6edd6ba7cd72116e12219934466ad70907e21cadca50e81d8457b3f0f8869820f02362321b02c65ccc358f9f6554ba933cb825939acf1e4ecb9af4362b4429ef4f8270640d55555e2fd403253b4ae2460650b87482d27415e1015860f9f1bfde1c24ccdd5c505010d8ca6464849b75b0dd58c57fc3a26d07a8ce62a6a56ef01167ead43d30a0202533a435a9a86ef93e109888200acae8f7913e7073ff16345fb69fae1202c7b55ad2c465001ac7a6e48a8308a37d996f9121ab1ee8f727162b6c8046fb5aaa3e31b5670ed958d1cbec1e41627bbcabccd703132c9cc41b4e9984ae07c90d46e88c1c1f0136a40d47dfa4e32a05a3c04f868681fcae51d16df8b159649f7e97c27296a1e6f3cff1108dd23fe55ccc6ee30223bb3980a9c418caaab2231832d71c63f177484296e74c65c6b7029d05f24a46f3064f1007c861c0a9bbcd30def40c60c7c09ed88d4b059fba13d012d365dc6aeaea94d9a5ebcca2ab2a8c77e6041ba3aa902b0086a436a4c8180af16a07591ab2fcfe29c7d48c04d2d1a86c8a4978005fee91e1a1f338ea33d7e05ba15e2e18ce167a36f8e56b349d9072e0268728a35a600247fd96bdbccee937f1ec099ceb66273b361137bb60b83044141908e7054a0689cb07610d2e18b9364cf25b9c3d847aedab73c02c918ec89dd99c72424666e21e13f2e1c193fc65f632aacfa305afd55c9d1a2c9c6caae370c088f776007a8d33653170e181e8431b91fe51c3d1a3323ca67c1400d51dadf386943326043a577bba860ff2bb62bf8383f8735b3d73c7db0e7f38509af1e092e967a22026ee1096b3db287fe82167ee91a8304229cd1aee85ebed7269d07e38ef6d178ee7c3d9b670e968d3c3af6ed9f04bfe45fb656a90d4cd573335c871456503065135f975969a2ff1313d6843b653d8fb13a53677b8198e357b2e890587aec051209339b482a6601fa984f4b95ad1cc502f1c2f970b06b7c3f16ebbe0281bde168b0b47f6e15cb15f3aa419ce9ae585474d0b1f8c5f8ea1bd0391febc548b99ce136c18fc34266725ec4be127b4b3b5d574e7696cee1dfbb6bd64181b8eefbb0b865ae1bdb85c18a41fce4bdba523d970b62d5c38da74e1452d51ade08d9a2bc2ce981c5a2af0b21d81933b44462f1667836e2fe82d64f45658df1cff77d76f284681c1f0b5d338cbf13d238ad17bb5c2cd72491bc7b506236591a1e910bea79f8ae72b018e211860901fb1abf85a5bdaf288fc28188ee3e350220932e650320ff55e8c11ec47e4ca371f7d7d36fb1b5d18211d54a6f322083aaab7ee66f2dfc32114e05b2bf634d0da280be0c7afaa7e3424600e98554413b9fdae10c92ec6c855a747d67631eac04196fb352f530879a14621e63cfac0bd746dba23f96b48103eb8b7db116de1ed61843c012cabe5413269e46ce555c180b0ea8cc2899d719e974934819b8fa74ed413d8309636bae20ff8bdaff9ca25e1bee08d9faa6290ad75c5a289e972abc1dcd5914b43fd8b257adcee3245338de47b2d259fe3f5ade6bfc33ec1697f560275785182f47da2ed3e68cb265259b298f1b3de1c8a618ce3ab4b7f557203115ed2ca05244e75c4483d99ad486a04dcad1cc91b02b38af2e7eff02b425b80ee80a842df5ee2d848ef80d4e2763c7e412921568ff5745295872204d941357b5bfcc9218ad3642d3c322f09356b4f647cbd8a726844a9c1965e2dd566ccc9d15a4542efa60341a9211ed595ac82b87b2a2d2b3aed64f3de76e01d4bcbafdda3fd16986ca0eb09833a3cc2fdc308c9bcec0aeb69947458930d222be4a9ddb3d7c709a1d4bc0102fdb8a93ee0a1f96c1e11828d7449d332a8318c270c3cf22e8a675ae761bbe23ac62a559383340292bd025c30d7b94b2780e94e748385745eeea00d6469a0a4d447177a18facadda0c46b5dbd688d6a644bd3f32e8499c751d24e6ae084ee0ba98a5f87356b069989359ae63da7b79ed19cfaabca5f677231165d9d62a6ccb4e77ee7bedfe328ceee3b831070dd0ded8a2a462563d8adb70b9ed6ea0efa34c389ebae4b07edcea3e16904340a40e2bc3f0933e03a3e0266cfa85663c1d0c43a4c7fe55956edd7caed2c8d572412ec71f19950d83236917312ffdbdbe1c080b97fe8f6866df5a533777ceb3f7bd3d1bb41ffbee80d682d37f406143097b1c9c705cb2e2b9d1c3d63fab3f22d19dccbd0331417e11cf980795341609d555205841846617d257e6fe8902fa1909e2d22b1d09ca2ed0c5d361d2dd722317822e1f1c4508535cbf07f54d7fb0c1d4ae80b0a678075d18153acc110c3fba4885c7e4aa68c0f35552c8e0deaf37750f802cc0a6d915ba2f6dd66e319915fab17b3987d34ca01cdb23dd831a589cf4c83802b9cd0b0dda2333e871453c329fc62e305966a55d315ad538ba4228ce4bded6b5ed2fa33306ca880c03ed0701f55ca602f84085b2d4b53e8859f7a0265b85f59e623f7075d5a83399d6cec85c3a810c56a339dc8a35b1fe885d4c904b189a0773fabb9506510f8aabd903c1d10a931f8be33012925282883705419b1f8484f4724b44bb15ab1a65f6c5f9387405b6e084001cc5afe650a0e3526c659a5fe607af0dc20905a48b208b1a2bf692641e130ed8bd8b8fdc3a1a1f4c7da244495f433115b9f07d45d06489d69feb5febe9bc23a06258f54702362d4f04af1d9407eec749b7dddf150588abb14d53f114164cbd89a1d39ef41572c489861a7cfca8f502946da9242176d189247186fa453a002033261710509fbfc8b8f8e643cd832e03fdb355adb4f912db9111a24821727b34788e3edd22e49dd23140b2789bca82deb3d3ba61a38d352274f9b627dda5aa7097b0779e1ae3ae10043901e41b457ba27d5f67ab17846dee4be4cccfce3d2b39cdb9017002d1948580bb5059c5b0f2d69cf2dc2e5f671b850c752b608119320708fbeab3fbb6624a1132baf49c4663e9311618e7c0c470a40f819c5a90836c3a847c48b684b3fa162e6604340969bec3fc82f0878d81e909500bc7b2f63461469e11f973aacc00a785bfec7b4d71bb9383797dd8d1c50ed100a2b5bfdb6943ab0fec578a790866d58a6377ebc503f5f24cdef1d7eb0611d08cceff9f229cb1b32eaa26808af93bbb0b3e443586d02f1b0777ea992bf2d631f046d9bdba010bf81b703b57253eb9ba28416a20f393f03c3d3469e26d7cd46108ea0138a2827870631fbce542c94c57dfd4542b664d8b374daf9b448d4db0d9cb1ef7a053fe60053b0fbee6cb95d1f7bd45a4b0836c387379a7d53757ab9d86704df745eac13ef438b8c864fdae10f872e4185a07744e7a6c1eb71beb1f9718b1c558d5e4da70d0460ac1082434444cebb8b35f2bc9661f3b58346448df6b37ec29364e9e914a8a2e4e14d99cef31c6bd2b0b99daff26f61afdcfcfbb1f3584012e97b81615e9d22c177e243f04d98ba02428ab825af0ec5e6027b13a934b68d83f6046e2a559cbb8c9126745a900f86240ca941fb4b5b4a61076ead3e41a56199da79eb7fe8647169931efc599238a7edfcc82b4ca63836cbfb201a1eebba39745c23b2e9df9bcdc9324825b766181ec2cd77844d65ede6d50ecae6a532167d09f02c70d98d55e50ce6e9f911d464ad067ad834f36317ce330c8db48a40244ea4a0cab58186023200b73f34445c212d944c20e9d1e3e101ceb5e3b3435ed8b3dbf0239395a0e66666b07cd4794d1abdf81b51745f75527538a6090e3ecf7407adbaa84821a64af79522c4954309fb16088c51939a27719658f6ae7a8833a2f2887048fdea2dff82a0c4d156bac5fb55d26c2d30d641c8146cbe50eadabae86c141f6e64bab34ec20773467e46cd0e3b5a3bc4f43541377ddf1b019efd1dfc02e2f25bc9be17591b4927bb7066d44b093fd6359631454e93734028fe1787f584fc4c6c8371d14164da3c329aa9a8a01aa1fc655a8a6b25f84e80748237508600482716f70d9745a482ef8de30d46b7fd2983e3272cd2c35164da534137a9da2a327cd5ad82bd31da198f372818e8f241cb4fa5353293e1fae079a664906642a2e2a2bdd12a445e433c5f3b624565ad4b5c7c560c08afb0c9a1d19bb65b45871ff457557008c8ad62913159ded1fb5b85c2c4ae8e2ade2a6249ddee39010af9b7a79d6b18dc56112e325824775cf2f6c5a28be0dba4800ed7b46d866e3a048f1c4382004415c3fbf47a1953978266ad3ec5b20d1a4d14115d458bd6fd0bd9ed5d0441f096714bd0e580e90da44b91d5ab416bee6698ff6f58c5ac2676b593e5dcbb14d8f2ef330732598442e378a022515d8ac13a607988e62cd8464f8058ec2eea8a87d1432335b6b49a223644fbdb1831bb2beb6e151b511acd37aa2b2d495732b11d4a444c56a8dca2652fc93c703dc4f599d832a522f55ba6020574f5c5762c57bc975371a8dae70762b3760558368adbdeea6602a04cc2d4fb093a5ff0b1413543980b61806747e9f60251ae0c30bcd585fcad37782a4ed2e833734acc3052e6ed8654f7dc302b9c7c6147d305d6d76cabd97140e70bf829bc6aaf2c1ff224f02ba6fb60b35756e6a92fca450a18bc99ace3263ab43a079b973dc43cf02bd630a8584d477412a48d3589553ec0dce334227208e02b5bda96b28295171093a0e09fa32835cbbcd18da70d47b771c7a3846665d0abf72e113b520b858604f58eb12282d5d63cf958c0c4ead028e93e2496bfd342c06d05d97c650472b19cf8975409025486ab14bfd65eec73aed7c2942cb32136d778f68e5dac48a3083ef78002667e35250b2585a18e7c5511a7861aa728833922a104e573a130d9b88da7104cab4b6a70af3b993a25301b07986a5049b07d3fd950dd970c63500f9f1e36fc6380f25785f477a312dd9aa70ce90d2126486f718366f58699790334204b6eec68ebcdf971eeaad2c959e9337c5267e17163c2d57bac1451cf395d483d8c5591bc167c439a22de9ef4fca9ddcb4e1aaa97ba680fabd948e8aff9d04640492155f1868442b7ec26e6bd89f0af3b6ec7dba6394473b4e64912819450f1b5044334ab75630d0c0de9c1ddefc33abf39eefc1e343861321e5d0b3b4c40bd0473748ae86c71a361116ed339dd6d99a0d6385d70254360d3bcf8572a89d6b172a3becc7e0644c200b4c9e42a5e82a4e8cb83e39371363866afd942dc9a022a7b0f99b63d59fbb30359f553016a9e2f592a747e95c7b68a02807c95368591d0f6f643c8ec38d265c2d7f0435d3884c09a431ea036a1c6eec564c544ad14aa00478cf39c9b44199f2f15cb9c02314c0138e8f1ca079cd20c0b678a17add03b389c780ff998c0539789eb73d4a1db8635f0ad6cacc2d40e9e01d8421fc1b8aa15c7c93223d4a4610cc127b3b37880f7728d977a20a6a246290708879e8d06d0705e4ebc9012677dc62c645e349abbffe2e90e3de63bfba4b710380d3318e4916a9dcf0459b4061f7b6185261b27f6e96f706962e2e0bed5d2a56d4ce7a6401170c1de828ae3a765a6215b757570bed6828ac6a5d5341ac414cd03d532c1c368cb7a58697abcb44c9771b44fd60dfd923550de2892d95d790674a55be95510815232149f341b49e19a04d565052261d8cbf0c2ba04e9e3420d1cfd95918ee853760a7f1faccfe4c0557677d4cdad92d0e34c48e12c8886f70b8034ae6501f38057500f4418fbddef0c5514cd4f45d5b423639021944bba40bcd8d77196e3e7d6d132d025fc72d0b9a8abf7daa939db0939a2f7dd30440971dba74914a71a81c12d6006e812acc177e50f8080d0eb7c5e58824210088a4265c9fab45ba1181fb3cc9910e02398d0ac4bc371f16748ad61f929e8133c622b14d1c71b5a43b7625304cb4e4c039930e962ffb41fef6aabe4958030b4ef2d220429991b8b4c46df57acbf739e2c30b1bca87a829549b85f46e0435bf390ede5f7092cc5c72b64567c8b339e09a6d11ee40d184333e168c97d7c72b4d4c5e6f839edd71900047ad4641c2178720b8674e4f00e4939b41f548a044c7be8d76ab0e5133e2fa9e818dc0521530c0c06fe135717c3835ae1c0fd293101ead250ffc31fb3691162c0186a4cad23072571507c90ddd80d385e9e69480bd4a814d8335614d1571cf7860faa611b646143bfefbecf8367343c815fdaf827e0d4c4262032eae185821741dac8c34c398107e1dd92759ab8c61a234402c804f19e21a83f8149e64c215d86e4838109fa0e575c002d9e6051ee0b7c4c6df23d08e6eee002c1d690360489918645e06306caa64ad3660ee4ef9f5ed75d8553679bf84e25c5707446c3ecb775b920e6fe72bedc4167e9ffdcb17f2e34bd48f0f7664ae4448a0565c7dd7780709e2f2e2184401e67195ac04fe6afedcaf93193bb1dd3531e0740acebe70fbe3704dc9dc223fb418cae6f57901e76557757da97087aa0c520e9f6fb5ed682d4a3ebb80d4bf7b0511b854de895e454a7941dea7620582d496870ea8d6992e7b6ca795f2556d083bf42478e88ba25aec3628578ebe5b86ed0c58c4ecaf6526b73d36f593927f1b20edfd3c3dded0550aedd294530fbd929120bfd67420261bc07e89a8220f57fcf46969027834b1c3c042c581f004993489e75e04cfaeb9d9b151f7309cb15b160c14a6a43fd120fd66e5193f46c17b76723e90fc8ffb183c2f66da3e88bc38ed0a0339c7a66225c22d6d17f283de92d96e9e263086c7829184cccaf58c288ee0e671cb306d748d2dc13dddfeb22ccc738d8f930eea1b4226f5a72fb493b07acb81f7bb2a89b716f5e3bf497847670b15a0dd15f440995f1fb9fca65fc091672216a9f931aa465b289e4492e7f9466408052ace72cfb68a27dbd268adda8b719bdb68b271600a85f51642ade3ef625d1c8b494405c4d346a777697aa3c866e68602f67cd1c9964261a8f60dd021c7292d6298ced5ca578810004604d00440b1e261676748b4f1a0a78d81894ab42b9a34935434b822dcc991093a4901291d3187742b4b44558c7a4a47700f0715a4218fe41dcaf71f1c346d2b55cf5a6a60c19719e2e24e092dd5ff2544f0a6c46124e0e124c3773ed528a629fd9dcf17a02deda19ae705643444da3f5ccca73e3a326599d3e8dde9521105adfb2224e6ad60efd26e1bcdf411a45b9880e8f4a97f64f3f5e8c2a8ce9131c8d1a7a0b75c539c0eae5c853180fd99972f6bf5bb60677d646012ae004f573669c674f2e404133200681339df575f55bd9110ccc879f8ed951ad44fbb18246641469ba32f8ab0c066c2196b4082353f79fd6c604335f1935c590ceb75bdc74870bd0f5395c4e0f8e712c6f7c0b11bec4320696b18fe25c84fbb7e47f506219a648acd39da4a1d6a49d1c41ae92e4086576fd88eb0dadfb5bb216cef4dc4c52295f2c1434fcdb4dd09a67b184819494a5586eac33f401257933d818e0aaa009f97555a85b184d0ca2f6a422dc13ad9e066555f3d8e23338f653ffbd0b43946a389ed0c4fc89176a686f89a1871976d627d10a7ecadf1ae675bdbe450185bd5a42fdf076f20e91af6e7178bdfe10a1ee5c87d3de6eef4e4dccfe733dd803e4eceec8c8ed39052c9f79cfc912d0c5b5072eec24ca590274e31f4dd8a83a824cf274d8da3909a151ee4b11bd0ea3893aeaedfce888525cc098b90138b1585f33793fa67c7bf2223425358e7027669ac4367bf5835a83abc2964eecfd99560bcf2689f5c0eb8dd3d0fbb4c74bb8bf8b12bbab9540de1a09014a3cded1294ce79769792cd052a025fb564c90f3e1cdef235dc37e681aa5634dac25e8ab7679135b04d5fa9195b8b28c55b2308cd843081992a52192dc999ba1b6376be0cddc5a6a8e16b555c812b43cb84ddaf988d92882758c527ea1ae3cb2e01acc64ced5e9b2037fa76273b8849e28a89a887b73970c505e42ff95c9bb0377cedf8072d8e2d2546d2cdb0b005036940172bf43eb132596eb23355d43eaaa19f387b69e2802961f2b772a609f04107a150a142aa77af5f68f6bbea155280e73e4b75fd41c8bf61b62864a49d1e6c62cef26666b1a7b4352583e45d67880e1a1b146f146a5f35f2ac7d1d7e5756eb7733a244559f518bd3899e23489d0b38cf1bf6d81ecbac0280b27dad408134633de3b5a2cd0ae52c52e4229399141b46888f3cb6d1dfe6b6930c3f9c1472bf6e29098675916f63f7a7e8654fd78135752d5e893710b9bf09b77608c34e01dd3b37e9342cf6a51899b6acae784da5635cc53bbf80d14eaf5377547a1c98dd25332a5e6c54cdc791bfd2e9b406a8434f32575db1ee56188aa5437114e12856dd99e0019fe10c9097799c57c7f3b1e5e332838418a24dc6451f274a0767268a18b2dc1c620cd3e28aae0f4117cc6048d53abe6c7c37fc96a13194bbe93ae04f7ae21dafc11c45cb6149e8f521fad7db9919347a5771faefd8f6535278cc4e6ef732f0d44e27e2b358d4c32b1b75f5eedb2ba6a26c9b407b8fb0c04ae9a13e93b92d4aebcab6665e8a2105ead91ce49b208fcc378191943d8923f631e0e27f601d19992085bbf73159072a20b252d5b87c0487b370c27b192eebcd7868a39283bd1d39c5afb2d19a9d8cfd767000fa32c1aece062f9f3d16b1ba716383ea10a459158e37613af9cf19352a9b85b15ba53f455aab397485d73693759640232bbd429f8b49b604bc2fdd9eefdc2b1c7ea1302cc3f0e543a215b2ac3251adb9cec60e835a3091f9662c31c6cbca70fdb0fd5a1b8458c05aefe87b85c2001b08790b663887f3c52a8c049bdcad5ac06e13360fc981ef204b70d8cf70e81375b486465bfdd9087380e24db440a7f8239344813cd2fb5ee6e6e5e972fae8a8254373bd0b8ce58751c1441fd737968aca2f6ae708e396a60d5e40757ce48116ffea932341905e4d0659c33a73dbe49a6a8ee5d5501f69da298b0e21ac461f80ac903055916419c13980b55ac06c39497090febb865c70b9a836751f47889d150566e4b3fdfc4d0864f345b8ae3979fe88346b81b0317abf1d6e5cc97a84432a473747de2545be1a37bc6d2c0759cca553cf7cb67c4f3b30b7654e2c6893fc7b1387aff145c372c32f074a22cef729dcef995222a72bc5d12a9740faaf62b6a070fea3244335a7d7d2945561d38e088df8fb1a7ce7a7a8fa2163399b4b20d32f8923b2985c172bad3c8d57c2bc35618dfa224f9f0d8bd807c8894f3198f2e4970edc333a0165c124bdd8012fe66e89e8b76f930992cbfdc0a2fe5c389cf3e253fb4ce333ecd830a03b5760298d3fa658cc6e9d8d52d4e91b3ae9790f896941595528a45620918c10a809ac1d74be4c2f95019bce61fa9eba52301b6aa45018a07309b95bd3936ad85f8857c1fb3109bb5dd39540103ef571f5c65bcfcff6549f167bae35f180f8e6a318c52ade95a7d9495009da51b6a6f98a3029ae36c353febf6cc367a092005ce96f57b9c33a2704430c75067531aab73c9bdb86d38e7abfbca6ee140d7a80631165ad59f81aaddbe507f77e5c3a72e69cabdc95fc87000ba52548e65b2fad3fe0c133af8d3df08eba4c0e43320f8f0e043f720f5bcd144f4ded0b2e768cab13b9824056205646110018fd82c2d0e6b15063d8bcdb21395deddacd9ac9da4cc54191aac20d038d8b76d23a21b045f6f5f9f195cd43ef4d92858e791779ad69ff9f713c9c16709674678bdb55273f30a5841b4b4c34aa63b7549e9ede176c3dd8b717ad378c3510b745a6d35a08cc11743a5bb5b4b708a087c7a4ce5ac038c3266b493d5d57df81749b2d5c8693fe9500e431084b3a02a4078c63b3c87aeec3b7b73e65e28fa53dd9462bfbc8504887cf476bb917067d76830fb03e48ee9b0403e049807ee34b5186b61e1147b2dd80f0ba6f201c5a6c60ed4034bb965808f5a8b69794b11ca9cf0b94ff293cdf71e6322c32e5abfb04821c1ac21541156c32e2bb3fc52216b1f0eb246c89a83c6d4b5b13936f105724a1afbb612029980db6b97be9a5d83ca49f1d8a13611b3029af558230a14782b7f8311652bf21a797cdccc49f8eb16d4c2648cfd1b33ae14bbefadd314d51735e3d0b582bb573fcb8a68280cba327ab68c577db85b85e5deeebdd43628f70af0696e5cf973ab9ca319f2954cb0ca2ac4f028627d29cda5145592c1c27e45f667e27652f17e8e845c75a63314f4305ad445e4fab1f3ab3bc7ef2350b794dd752e3b17b1143d6220eeab0e43aab882156123675a8261519c954970e3cf206b272db645486cf92345973e1d1e6e9c87b80f708d49315b222f85eb6752d15006424a4c7e49e982575bb5d09feef2990bcebaddd0cbb8ce98866687b9505897222466e9ba35d5500d01e8456c3154a31257ec09e544e6e6a5a261774450a0cb01e869e7209ed77bc70f3723cc7de781da527cf20e36a5bd2ed0edc89d6ecc1112831910823de85df15e91fe8230913a0d207b20de09aa352eae5834bf10c72faecaa7a65f52f66dd0d88aa44270efff23a4bb3e67c76207e43a4ea1fac905941ba480196f3b3b06a22928f6d83324890248801bb35ca406bf9d2582366594c11a4a258261a56785cd7f0289aba68d12d2e5157a856f2c95f020b5f930c37d12371c8a7c6c37d00406bee5efbc8a948341fbcbbc32548c1a5432d3a5ed338753bc2df04080656b66be586c636facbc0a52b2f90d2a939237a59e6f44a111922f1999ce641c6cac1db04b4579746573acabdd6648d57a39306b65d7046d601370f1034f64288d17bad1196d9dce4d8e25a2ac181b4612ddcf4a15f582ab69630b44947578d583f1d05e2ca81432d209d91879c110c7c7ccc0086f91c181fe9b6e4f2174e97a5f48c22d7e3e4191d0e4d9fecb8f5cad25a4ff07b106f9d23f4d70b21f1b82bf43e8118b40fcf94b40cf633e7c374d829fd19c63ed3bdf6bad410c7623409c0e5a79e9ae6b89bf84f61d140b8bf793df9571271212b6d4418f2c273a0cb48dab1b15faeb418324fc54530d0916e90d2bd77488e20da0cdb6b4829d1cf9fd8a2d30f0f1753e36368d3bed48128f8792f97ed6779ba1bb0c369994e15b84f7c04fe02e0dd65f7c13776fafa0ebd8999e97c74c948f7daae446f5bcb5c2958964644c8ed4532df038bc1d1df385fac0b1c789b1678e85ed7ebe994d0541fa21bf390c9747c7be28859cbbfb4a270ea1d299572f8d105df6814f178c40a3487df14347d08f89d2c4e1e3fce6f5b7b6fb05729434c3df73ad7e1ec5e39a752cb4613ea4584328edbede10abfcd38dfdcc5c93460527cac90485a82e05a70a194e3060fc4147d74ca25195514646a48e6410603ec7611c44c464731fa0a52860b023b35d23bfafa526394087938a8aa05b8585ae61d0a1f532bb00d51ab3ddb399bef9d9549da7c257acf402dac872312419704a5abd9003e6aed806bb51b47e30e0cda5b052c3c1a36f4b72f7ebe3f9a1a60fcd320026c59f81a8226d53ac39cdb70f909fce7f4164ce7207e790b418c0252fbc1890fa12f2c89be0622a10aa518ba634f8887f82c6c0c3e42a2afbb8afee44152df4a76a67f9cdf2b57b8c5ab3e7100a756f2290db353ea2e3fb16fdefa2ec7baa551e1835fbf0531be186398f924f68cac0fb22862ab9014b35ff1eb428003ceea78b1426bb39fa20969232a6392eaa39277d2fbcf46dbac2096401b4a10d5a32fe70dd0b1e314a4e0a616f472a943c769f75cf5a218beb511e3b857c95684c2debea803eca0edc357268c68d4019065c86c68e726e32fdc3ac2486e004b01c068fb4faa355073ddc7afcf93759087b776acebf98a8fbc3a15fbcb984b199c4c89d857f3339ef4d7e93a81dd0f5b97fe5997f485996ec006767b050efa0be47c64aaba85cc1ba9cb5b7abccf02d40cf6e2aa846447bfd8ac255cc7467ddd9552d1190c89d3daf9f1d2e260cd641784feaf121d60c277f207a822543e1b6653307b04e8713be01bfe8f8cc6fc82193ade4fe067f09de1a39e46482dd7ed08ba6921583215e3d41767fe1323957db653eb124ec559b25162ba5c8c90c5305d79ec647032f7439259aab89e1d229a95f0b6ee0277bea8ad326fdc89eeae2c4fb62224e185989a133f59a0630c42eb6b16573d1114a912df1cbaa366afd747527320c9d3b631dd9ceb95919120d17186cd8a50bbc906aa16dc98b1ef92412ac4c95339eebb334fe0cd3652612f878882cd60ab0588948b011f20f554722f9ab0fcea97709bc64aa99259d28794d84106b577e4c00a696236b053f41d29ad868c4eb8928dbbb102f89c476d34fb366a1136a33ad42a4c6e65bc5d49d5ff4d7d78bc8e1243ac3cab0dc125e255f77e1d05c8afa37a073b580a8953ef2088375e6c7fe0c37f61fd2b88e4cfc253abb20712acbae1787c969fde9208504512d9ea69b92bcfda3e06c728e044f5dcc3837453230feba1da078a5113433459767095091fd8a85db3ec1eb001b0208373cdade4d0ace89bf0e006383472bfe3b0e5f0a652d339c6a91f7fd2bc1fc46a97cb6fb345ef47ac09c41504614eceab00cfe7f570b01c4f25a8e5cd0e10d3d55b20dd557affa316a779b8b7e42d6395ece0b5b8cfdbea2c921382a4727403514561947b6e85502975c60e8785ae27e532c7fd95cf1750db969760f7dba8002ede908e5a220ed96664caf06eefa963aad62c3cd6ed3ba20a89b97e9536d074d26b13afedb69564773b8b3b6faf28e9888deaaeefbae7ac8edabfeabe873f4572aa80cf6abd37ca9a40e2fc4103a18b4e66bdf02b43e6ed15088bb2d3905fc6633ac82ad47f7d0c9362f6cea18f43dc3f861264a90ecbae135105afdd8932025fda056790fde8fc3da867947fb1f77d8681c654ff535484d383509f17d5c57f32b66d30f112de8247ec4ec9804ade57d876958e9dc198048d3c89d96a9b70c3f8395963a265e863c50da4ccfe735d16d021edeab78a0efae0f5b0ff8ea3f98954354a1c6928d8bc4446d9b92dd6a6cd9d760bbea0be709d0bdd8eaea632bffe73bc296c6634f5fcadf42ca7230f76a420ab10dda82839420cf71784d7854c37e63f9fcc60ccbcc39eb1d84c0578b526641c5d64313a3274967c53014829af8db67040008fec3512e0b299ad3c5870bebf5b04c012d3ee4c2c44dd23158b3a5d8363c0581b8a4c2804cbdeac4ee8cff27e7d601fd1a8e847587647c3db0fbcded65eb384b2b49507c4b0973925bc794b14ddd8237425e9e428b7aaf8d956243b3c0ee60dc8380b9efcc34210f6518e67e773ae02985457b3a6c070a08d0c733b6334528e2f116d7e2557fa9c3d24b731cf79c40ef7768620e6348a3e778db296f410abd6dfeece86cb5b65e9d4d052f044cce387d1788e4a8ce2598e63ae74b550eb7e1da8221abb3772fdd3aba8812bb2e1244f980a6660e6f1c5d6c553ced3fa5428602f7060183c8946a77e18601265275fdebe8028f8a8cda54af60b1060136f2d8f908b5d825689275de2bbd930ca211520c39a984eac51c3bc3a749abff9d3102259fa9e1d124590066d11b27c42fcf83c26eb8cd9ae7184d31784c190d44c6ed9bf4ed696b1f2c3559687ad34c9cbc49e62db3e0f16622519fe53ace4eba6e5bb4022c42abe6dbc7fe1ad8e53595855bc43a2d34e6840a04d10af48213a095f2092757ad1a1b0eb3020cbeae0e4f73b4f0de5ac17bd6c4ab54b4b41592cefd0ed242bf0c6e272bfb08b43f2d5f63c099134c24bd2abc1b5662ee0a900e720665511f27115ef47c8d04a742af5d6ced5735097b188e67cf85c1f6fa6c712c0c94685cf0aed7e86ceb46f308b6f7f8606bb06846fca7c5e32c5ed4ffe7d612511da491350e6aaae0dc52d70780a22101f783831bc6152e8352e6a215f5437c430aa784bf44f115ac21099e973a5e8df71333fc09ea1593b670a417b51e7bd02a8503fb7113c2b7fd449c20b8b6e7a3f9e12fe3f211f608840d018c95491b2114decbbc7798abe2c165125828d18a829bb056c1f700a6bf8a89b2f4551e4ef3f5206d00b4c667d52a45350582f7c5651ae861d27a724e900121d547f3289db3d93683ea44591bb790e6c5c8f74b23b6ea3619d14ed91abc878ac77cc23aeacf082266986cda4c327bca3033d2cead75475a1ba5635214f5ff44378371374c5cb962f285173f75e18799b55c61f11b0b06f572f89264ddabcdd7a51806e683f43e6bbb36146bbf107e47a5c9a88577530cf8933a7f6745962283cc01cfee0d25d1b713d8915419f6357d8bfde5c7b95dca379fc73d6f0b52c4a55e08787bc6393467f715e16d51e957672c63be7534938ecc20de9604d86dd56a691d74e9d998eaeaba0892dd3649e61535d86c5d915708adfa5fd79fd33863c2f44c862de8a6306c8f7aced3dbf8b5585d4221205430b0ef84651cc52a8c7fffef87ff50d3b619f90d95b8f70ad38ea85213565d28baaf6e9a00af4563c42aa1259a2185d5f339100c085e9772114c2a6a9649ad8c0120fb1be881c3e41a8b562adfd63f1d302b380413594fd4dced99ee68fc70444162d56073abc82fa1eea52ae1c14c5e880c9ace1b4007abbd79427177b4882d5ea0bc9c1d56e9afbed17f2fead0db44aa544e00312de62a10b1c273ba1df477156e10e9b53aaf252c2e63c065782367e7f4831110f5bc0ab95e9b63a447eef5570d946a2a6f830a55de5472063d093dfda94e6576189b93ef383cdbc3d4a954187bfac50a932e44b864a465ecd40590fd0126142cb123102a3be70bf7271da6835e3c62f27f29d1f60a44f0081658a839b432257774c46091bde0b28269f11d835606b15871dacbe3307b0a235fe054b7669b4f493017ca0f057d0eb50fb2c9919ad6d3abf402377de9a816050a7a2e0390ba17c63b7db4eee2e7bb8e2c848792ff450fec54a42850a094e116383f2c340f27c0c433dd6c2c725710a81348055e72cdf208b3a88ff001a6a31b915d19df403d21f61e3db6fc77a6804a8f8b0863d4994504224ebef73e2f3cafbf88091c1ae2f015f2e5dd76f63dfb95f1ffc219e5f11191433e821156fee93df35f9ee1c6f00cc9eb3bc3fea3170fde04a4dc95a12ad2164e3c3a2bed0922e4564976554342fe73531c14c28c8469b3aabd8e19baec36885cf202b2225ffb0b89dc042453eefbfa3b7451c3459cb20df779b9fbb19dda4d242f4a591a52f2c3a4170c3e054cac3bb0bf01b26ac204269e302d70dc1daf2774a890c79a356d7dac857416dde4d3b1649bf1f25448028ce4ed393b7da145d3a20807287c89c17cb8180a5b5c282b1532b09e41b8930ec7684495966cce0a27d64c74640c50c4bcb0ff3f273185338f2177cf90d01e5cf36bcfcea33cde7ed3a7098f389b19f7b87a0d7c0bcab9a934c07875b98d4de690c5d2526a078ce22ecf9d8a34f75e3e77eea922b88e897884b8161fd674e3a8895e4165015208b18a1217686a637de0c8906059456b4cda72ba00debbc7a82f0867f08945b2de319b60f479121e5edd4d0a18e80a1620eda50e0362ef2fe1e58d630b03878d2a51043f9b613d72a4ff7a7318d33cbb5abaf8b607077a5e4a72e9eab3ea01ec0445d6e4a983b24f198f43e0af8e82c33bad35ee8407a7a8d38291fa1f497f528c0a6d43f290d6079103025f87dab7483d46510f6ee61608e0af17caa24e8900532700114659c4f4b450ae2506cacbb1dd51c91c158d706ad02bc04c8c9ef748a2512d66781407b6980ae2395336834eee7e6395aeab73c2b0ea222622e608768798287aa5f460f6fece1c1a88f09f365fdadc6fb5a44abe986f4ee804c14a2d598b46de1548c2b5a9b635be83298b755f4452bb365ba3af95eed82159001647b58c900340fcc87dcdb09deb1553822b67c111e28d8be7e246994b0580fb17ddd6448978724a7c5a70fb8d4b5f27aa8a8ad949715aea11b3288d83257074031b74d3d1f41beab61feaded19e322689fe91316a3aea827ec5d2b1d12564a614784d4a4cb40da7781c3f388dd0be57f939208b9d46495b7ee7121006d4fd7b1ebe347b80ea89c46e1343506695d187a1859ed4345b3dc525a2d7a7b0d2a17a351c160a7c904d50c293857aea73b43b1c9cedbfaaeee591dc26d91df66b9ae081fb29f911e575b9134a450f83c6838df73b6468a2157d7c474dc23242674cab869e477d1e17c2e65dbf2c319c50704d3529860383468de14361f97813372047ea4608b75566100a64efcea12f631ce118a2909ceb4698b72db4e44290d82d620a88b33f3e973c2926d3eff8a36160dcde0bafe054772ce8d11628e3d96882205bca4373ae1c750c032ce8cfee8b43b13dae360d6507ff5b1a8a0280fd11e194b623228f9ce3f47c19cb05e4bdebaad037e1713cb0e431e00ce0fe7ff5e908a4bdb10f17ba2d0df647fbebcdb36f442b836e41807bd7e619a02261e007e370b5e310c4bf8f9fc740d4258c0a1eed554bf937f5fb802dd600d7d45f4bd09bf9d815acbacb2530e23368d6545165248cda4866c0dca03f70db940ea35a53f82a968fa6af1c7da49942c811b5a0d929a170d1ba5103d080e7a58bf64080fede3a9c69e6d82c5508b1dc4ae8ebd0b2639bced0ac60405fb90da989197eeb68f7095de636b28e54056ae285d56f2ecacd824ed4b02146aaebef801257b0065d2a36e3f33a87e92b8cc551eda42809f2efea002f0494f54029d6d6a5e93139822ba1c0aba676897c4ac1d8299307205b308c8ff4670e131c18d5de5406208cbf9923a37e7fe081f05cf880289d9676acab028e50f1a72f9db1f3e87459685488949d0b6ac3885b04475daf5c8aa4a97b8fd978b4232962f1607a32035544b5f86d28e9c04759fe532505ff89f9095e878d220f1415a2587abd7476515e251765c57fca0abdc3379f1cc70f58fab6843a37e014436aef9ed16e997f183d47206247a4242cfbd3cf89e33ad7bbc8b60f65939471f3baa816c1b4a2160394a046507f5b80bb98c163298f79063b8acd69f18cb37547a46156f2b412be35250fb11cc1a9600ab4f50cc1142d0a3136f84774819e9569687a698a7e2af5d1a4ae220a3a651de3d7f0d3acb57f29926c19f795ae6ebf5119e867fe3782c813c3cdea35cc8713fe0c9489cc87e1437434d3ecfe9560b6ff41ffb09cedf80afc8dd01428ac4d2b7e37ad3c77de7b7751e6f4dcbe927b9654020ff89c9406b530e734dae32c318871432185b2a69d460eaca6d91980626c11052dc6339c00bef934dd882bf038f511fb119a6394a2f563096c53ccb33218b29a32159c43da487dc7dc317b07e283d95701360ab0a853e16781963aa69ea606597377878b32ea33166587742b64c81996509d0299197b943a9cbc4c22df2623d21c89e3122525760b3174a6b83adac18df62e185595cbb24946cea8414c4c2911b7d8fc497de79de88c3d90f8cc9d30b1b54046dc11db56fd0eefc7db697be8f6132269be6ed9e7e042acf7c85020c0dc010b8dfe68732d432f0f3406d22f725a0e19944833f5e786921e287aed3ffe22b611b3522e8160c7a69caf6a3e41d81898de4b07f3417e6cde0a64d6803c6907e1cd7800bbdfa770198ee0f11bca5dc65bbb7c9a912a896a4055ea83905105909eac8e9489bcf95773bc834dbc3797548e7721f74a8872f0888e4295801431ef9dda852ac8cf6ced38970ebd79990564e623376c9b315790273aec73349af23bdbd759700c15c98c4bc076d88c224fdc5dc17ee9bdb013c787d01f10f9f4e5a6637be980ba413ad5210456633dc0157d4cdf6c09ba6647fec476f7b9ce6be179ce0adeb9c9452593872a73cd4c785d5b50926d39d89fea73ac6ad27dcc5078beb69394cba4e0715708e4080a4f50d453fc27b7cb7ccb7fbc866bc89ad224b247e3df80cf0573ecad8042bcaeccc420cdb2aa9e553f7e80d73195dade136b243909607a827db0cc900ba1f662bdfe5f0c184e1f7080359cffa39b24098e9c6c6ecf4cacd1bac47df144c992585831aaa53587adf69ae6499441ab06310817b22d8dfa41a344c1faeed80eec4dd8ba9fe8aaf3b7d17fce0600cdffcb7fe387ad255a3703f3d132977600e507aba2c9588ad8553cb82fcee414ab29a9d80e293e58903dc65fb2875400a266d24138e4941af382391b56b375fccc43b2db850dfec18d1c5248bbb17963e40a992bce43c17faf48503dc39203a2ad145641ef9c5efcb1cf2a733b2474c257dd21deb751a7329bc6de6b3f453f7087ccf8511388a9239b47ee194fb39a7f02c56e58512fa9a41f05f203f1800cd97fc6646c6a294bc1658e3257bc11e7050b11965af9c3a5352d3dc0cf119bfc216bf831279a40ebe690b965f5395e24fcccecccb86e4ada5e080fd752049d2f1338d61290a982e12edb62e67ef138b554439117272e3de858fefa969fba0d9ebd1c81fba293ee1f4aee8a2cc47768aba692e0c8b667e62c6c3e41cbd94b01b36a182b67ff555b089fdc5d0c078a83f68e4683f9e18ddfb738f5f5234f08ca25b5f861a3ef0fa0aeaa6f1570927e226d41fcc049a3905539462b82793c02ed83a11eabd834258d39155db81c824ad2ed7536fbaaaef306972000e33b6054f50e9558c3a8f4d86b15bfc5d17ca098be4138545c94bf4f990598eb61a836e105cb73d4d8cef1f50f2dec24bd93dc17c9f12874e6be56b6fc1b538feaef31820c8186070631c460c08427d516dece4a8054c0d108154efa3789a33c3db2122de13818a257b8dd9b37c9272ad5ba2510c8c518d5d0c36427faa4947065c5a27bb47b02e3e6b1a1f4022d82aa3ef332c15120d3fb2728602fe3d57b1b95938f749a2d2845fe5d40c0a0256f35c402ceba3af010415a9005d0ccf09e233fbc188e799eb76308a037d058c58ea02f44df7e1d22e1cf041ad0c23325898fbbec266e5886fe883d5d8f56a55e77a8def3f79d976cd803f6408ff74eeeeba401acbf6749b61d45bf2bc6f3e693d8c4b7e8d823d8ff5959fc0c4147df075506db02c4f1194c41c1afac62c770e8aa1d9864b373be7fd9b824c7d25cd15587deb8bc99510db6f7ebcd5b9daa7f34e262f919f81a0f038d4036dda163152c5db82594c8b3a9ef498c2e9e4d42aefb3c7b84845e03dabd68a8bc2a2ccf50c639f19413fcd2a84a2b9f5d5a8b364ebd0d05ae606572337dbabafcd615da0f8b3c96976f3a38b627f1a13037e08833fb0f05ff8a189e508b29fd4b7b570c94129d584d65865bfcdc63c029eeacb04a90f0ca332ba7e91983ccc909417c4ee081db59376455a538c34b1371ed4a69b4b5b252a3f5d103dfceef3497aa5c52ea0e3611f6c8803d1f46032a0009ddc603c7b6ddb08694f816bea03b7a94c8ba6376cccf7be21913de519659fe741086feb3ecdbc91bef865b5ee454e5bba5df4b0e98059534549c7933bfe42878bac5e99dc19e8d8ae2e0d02c74dbb26587a99cee70395179ccfc80276aa40051a425aee49928ccdc040fa86737eaa963188ed3d301d03c83c4adf030ffd786d5060c0f7e0f8cf62fc3ba295514e2a073174509c52817a5a13ce4b59a0973ea9d203636f5cc7a954ed97519e974afd0db5fdb706e06806df9035109ac480fb0b5673b915118f675b283600d0de5f17d0f388da4448ca8cb8e250f8a1973a4c64f3350bc0b8b13e8b9af1cf910e3afab46fb08e7748273f27acd7508ce25894f7691f1410815460000c53b26125da69769b485ef981abde578c4c1ba2683f57343834daff360f9e99366e6cf8de737c4747f2ca66730dfd0ffbe921e32f1b0049dc6b186803e7bbe1790808504c440c71d2e256948474c34b55612af4bf14cf5afe8b374ba152fcf318b5b3d6501c0f0bad6f475090530eba4431fb868b0e6e5fc212c134e56f19759f1ad8de3f1588f8d7f879dbd689ca27090d7e35392765e47467404e5401e073a5245c131abb0e3500b21e30b82bfddb1bc7abb5001c56632c0c73bcc38c7e89a270754416f11ca0602836afdeebe9434dbceedf329ad61223f0e59876dc442ce15fe5e5ca8001d78ec4bfb4fcbe18103d5401945b9ef19f373c50faa1e74251b7fa00549ee871e18cbad88c6e1c71733fcf7cd7f265a240929748bee3f3e0e76be22f0cf245171151e2c21740e204f6013bc30050333f7d52d9c0a3feb72dcb7fae3a22f19d5a7de3f8bfad4eea9e06b670f7e7c09f89111bd6a041e91a657de007e83995466d98c64692316b98993b5e85464c079cde63b48e869fc97621f9b9a592d24c86b4eb88de5b84921d5d875d79a40ce74655ad2c2d5ccdd978351e81583d21242de3f3a9e1bebd2c639c9a8d12264591ef23e4514e43e13ad63baf232487c2c7a6015135159dda1742c7e5215cc033b552518086f41ca8f2e9a1ffab991b5b3ac194daab5613cc66fc64028710d4790097acd85eafd32e37c40072f70039cb7036001b3fa105d1704d5a133c13227d7cdc5454205534262b0367b60a99db0657c997dae9dd8aad2dd770fb0b7e2bd37f32264b90804306b2bd17fead0772958c4706a5efb1abce45b8bb905ae47e48fb25f7933fa4b8c0b4cfa392f3599ed3cc5d20b9369a9084f654a775ae8996087df86ddbd9f5ec3c45f8072c49416a1412f2f680e2c6a39b4fc5d70f7e145eb94259efb210b08106005935759df6b2be0613ee8243f5514b3eb888caa9fee8a30efebdd8a7def60508eb17409bb90aa6c227e74ace9a31da11d3a115a68a5e1d58097e4f84329e1890b7ab72d987b53d2192ed07940989aa35b2945d7da7863e55c8ddece4f871d17e82c041cd52d7f185945c2c47731f98049e76e0b2d80ea44bae641a93b21f1cc9b158388949b198e79b598916ec3260a48d6993239e34d9cda57e6c7590c73aa9c16bd43ccedb608a032a194b589dc739e937e625bbd18581c88d6bfe3e0b8f0d643e53313365ce271e32313d4ee157849723acf717cd88314c8c09567e33db46301a5bd772fff8bd4cb84b261b117a1663354d62ae81dd8090ff259081f74fccb53a29892ef438e9a0596885db40e9b7246fe8db47f20a910015746ea89ffc6e66dee8d57722bb65eeec66c59638dba9c99d80f89fb625b81501aa99534bc9765b4ee208857f359d80ae41034eee77c44cd71c27a5c3f00920b4130d48c1a3ea8389dfd9cd2f0662d8e5e9bdcccc4c88f4ff3a8ea80f145adaf40468533e6eaf417bb6b904e47418b1629ff44f31b5bb0327f5f4a1090cb1b11bdd80a1fd710653a4ccf298f0c8cbb3d2dbd6b858210bdf14037d0f87270439bd4bebd5bc6213b60618e1b9651b79b32e62bb4bd3d771df3fa2a917db3e197c6291435639385a8934d94145c1daf540a9d78215aebccc805598ca77beddec3e6bd3ef79eec26ed18ce5ec0b38eb8741a41e34a857c4b4f2bc5e8eec18ff65d91460744fcf4bd35e3ede91df4d0a793f5989c719be836d32db30fc1cf73a2b1116874d378aa0b485bcc7a86a9674b830cb99b5a14b98af06c736e2684bc9f77932fac64d54124c2655ef3d05051585040ce0ba9d070ae0815dac62e31c75399043c8766fc17b020fa8776dfe54bdba58442948a8c7cc57618f53c68fda37ba615fc0323271fe6e37a4853280922754008c6fb2c5d3ecf10360d5621c314e3b592e454410bff2006ca1211d5520cda010092b4f3c424abb8f5e472357037d0a0dc96ec93cafac6ba46d20540d7701b4e2b2a77bd2a58ced4c84855bd308b7fb00f8d647a1c232d138d2010873530526875202e797e1749582a03d2b5f6eb57c80f8843dce53a70e461997dc8a3367fe3e1597a58c3f2b7035731e41ee1db647a51ebef72721481042a1922b0e6be828f6e6df7b09fa06034639f4f15ac882af6d1725df1fca8b7546894cad9c73704ad643c5d700347f291919500ace589bfb0b41eb5eb82c3ae0b5a9552fa496916183d4aa6f441ebb8494aa61c24a87e2cec4ce8e301411d2af7db5bbc986b8d3a6488e0cc5efc5bc80d33441b5dd3732e4d3cad409b21a99e31fff14de4302edb51dc3e7daf93244962b37f00513c95c6f5d039a61e2f00ee945489875a2c2a5abf11b89facc94769c54e732d4dac4086f400d8c85d25ffbfea539446861a60250ba435e1f21f7226098014c0a090cbe65a0e04e2d612e02b8879da8dd6dc9adc4a28150618e8bb32d3ed33026ebe773b357483a91784590aa48aae30ab37a29ed831a8a27e230d68ade89b446d734553fcd02481bcf6fd0fbdcec2b9b53c20083f20e6223d007686bce57d9003786f63849d95cdcac54a65a992cd9a31cecc08dd8c02737a29a8343cdf76ca1948beb31550e6907543273743d238774bd3fd4c4097207ef988a02ea2a4d57f0497b0a1a6aae1a8c1d697da36f253e3ca86cb04cb1213ba7f7d6239629111483154e38ed5c9cf328464d66ae3cc1d5d16a27b56ca54dcc23b35769a2b041a71f566e0d3789b06b034e9c7c05878ba6f4549d08f5dcfc809f84d385224e6edc1db07e56cf818f2f2f06bea74337c16e7182fcbd04450ef893338a79d27200257b6bdf1480928dcc651f35f2c21a4123f79c946b50ededffd0e3de6833096d984f295ab70985252b04ef7b0408d8e6ff66a3b2685cf7440ba13e4a70c42149cf114e4861a14bd1ee82061286cfd6876b3bd79d8c770a2d5c2c21b02c70177a828623619e1be871f9a10fa9a0030ea37afa899e8c3594c12913c60a7434d79700c127422fc157560307d9c9dc791112cc1d9cc7fe7543d34b626f1f72dfe203371aa129d8460631816e9f9dca5e3c38798eb7e10d7b04de6d7775a10159b7f7702fb0414a0dda308d5fd175e58dd133fce9558ede011299c2ab8fc96bb5ac843364604ea3548a255aaa8b78560d0f8b2d69b1f566a27d6c8e3585b382c95cb912900bd09e74ec7772e44683e208ebf14cd521acdc5a9eae041ee279e8779c5b187812350cb1b8e63d8874582eb3785a4f2321d8cf04e9a8bd27e366aa5ad3f0823b179890b1124b82d9b2246ec1accc5c2934990d0067010a3f271778a907ff0309bcd960cc8f10f23646d64365a5a2ffd28d5157baaf9148d7a8e0896c550188120dbad394b495ec8c60cce354f0de390974d29dcd2f51a7acf3360afc875810e932e29b5a42eca0b0bff0a841d37f68d1fb2ea1cdf4ee3770a1b6fd3f840843c85b46dff81bc648a06e7e71b7d26f039563a26a71db362b1fa8ad38f011ede190dc29ab610cd959d2b8e879fded34fe4faba6e8415899a58665c0a6fe67413c9268f8f9b20547c8f87aef20fbed0c86ba1c59e4d3424f4a993b785b0fc3aa3107ce4f5c2b096947e0a35162017508831b55596d33eb0983d032fcb33dbe344f89351a4cddff7b526f3364d9c237eafff650e90f62735e11c19db9f05fdef51bc4517be64987adc7823911a654d6661cced9690368926c4dbf88dfd1e115aee47f4ac0682987eb0f4c37e7c2457cd1aae802820b6fbf17a74b0f9057a27f77de03748c8d76d403045d3c660bb3e81977d068edfe71d4289e0d43995ddbf5128cae78f1b82c462ac1acd05e6c607ac638b97ef80a3942f93ad878184b1fd0b0e44fa1322c5d67ef9d9d43cc9b4dfb126925276d9a393949313299ca279c19a9886b0719a3eea84ab921355d0b5c8a5b7fc755f71f3d1d2f2d737b07e8a8157e01a3b2023847e571f7eae666c742bded7b132f335c5c8e68fad88735f307c6d8e3ab415ca197baee3fcda6c263b6a0bef68012f6dc9e7ebe9da19879091ae72df08cbb1d76ada9a0583ccfd811847316aa6864f35eb1b3231e61230680cb6f9ee9d3d9307c2a73f09351add45bc82629891e588caf90f3be2ea68308347b7410d6bba6018aa5091ac93f938c4bf14a1d5a1e7c83e4243acaca824753db27e8046dd31e6da8d4f9f56d7a1971ce8330592348453fb8e4fd2b23f401ce6a2068a0670019ab7936f8f2918a98732edbe58e3c7edae67d1210324fbb98e7d1ad95529c053a8cd9051334193926e33a97fc3855bb248b8c183ecfbe699a5714f0c4c325170476382d510ee8e3b82470b83e0d87770dcb15896a1d1d36735755799326fd820d78da0347ad77dca775dd63a1880aa7f1d91dbc1015b360b3ae129d2f0b0839d5ed0e6d1509ffd7903da3330ff331b8bfedddbe21e5318c5065a81b63651d177aa5be2ce6cd7c280ed059e7e1ee0a0bec001af41d0b43ed80eb95e696d5f7ab9f89d70051d404efa422ea5dd53dac70fb0736606e4fd178ba6539f0a5ff1e66be737d612c7bd3c1cd32a10a8a1c9b966a9388b3352fc30dbd3ae9aa65ef6b355e602cfe639b2d04d776da42187a23435ba60eed66b2c533f114256ccd2ff32c6500796741f020d79a4ee6298289ffd6164e2295e0bffc10d855272b4bb20996dc100dc656c52e20e53b6bb846a0493b8bb26fe5e03c06df6765576b53db1df4d1c186e047d590470f20f6cf8b97b612c3a1902628715a4be05c618054434bfbe371119a671089e4bbc4bbd89a5a37a8ecf95b63fae40f15b712b5b73ebe94d25a57f2170eee8fee6b702cc663885d01e497837f84db8212800374a5a20a207ada101218d44000a36650816722406ba491ec17d12938f9860fb2d89a18f2043317b64d3f0112f6cdc9af135791080e9bf06bdc345fbbc990c71c15736b79e9b90ff2a1bd82db2daafc9c1b320905191356261659e40222ce1f765fd45c6dcbf3bbaaad7fcb2c624620d40328b531a1d3f3794ee5cd9e1e4d5ae67c079001198409e9ea27253aea0595ecbc1273ae1738fea6adb9ad5ee69cb2e2b3588814db1c8c71f818b6de797d74e04d9017c90ffeb71ba2cc76720a423cb9b7061a334fcabe81a0692dd84ff5fdc99a28debb948c8386d20b842b3ece9b9ff599ab669ea1ace194e3bda9cace987101794ca82e08e9b2a21a3c137edd027947dabf3edc89ed78c60dc11fe1ba27aca1b8cdfa692c6c742cfdba7af2f55cd248b1d38fe00436fe0f9999ae447fa8b2b399128db4e4b8f155890dd38b53ddd2171d58134a2d57867cfe3a2e381966d307501c65e914656d5e511742c8fe1415f0a5e9431e3263e916598bb220d7132644ede25e81feaf93a82ac19c3a03f3ab4f195af06450b38ddc9d990cb135d53c8723eb8f37f5dcddae0472b58c4d152d08bd1a1f42c2782c76b49f6681f394fccdb67703d1d642b17beb62df8caf24fa8c4928ccd2862b26b45c24d03537a2fae1b0068d726e19559d50dab6647474ab424473d4f37646d31ff678a9630943a15f132276dee6de00691d64947c0c4245d0d8cf45d7cb211afa29879fa153c6a3829fc355bc0fdfd890f018075a467b70fb226fb4d51e69bf53c073adbb3954bc7565aaea1c57206cb78cfe361ac0b5a84360176a5f7c693ebe873c8b3e4a7f4369838db4cacdc9d381b6434a24cfd4d42da5ec850749a1cf53d7743d8896e9f40d8d58d2ff72a8c6cb3792fbb1f8ea19f53bef2f2f3e515e3588d6b243059c011e4e2c050ff8440e399f4384276e77911fd163435024a3f0d405e5056554d1bc3ae9ce51db01c706d5140a9629ca6567657453fd1e0125657dd3239e28bb00be5d4bafc935df0c2d2ee84c331b30b0000f61603348eb0009598e69579d1f1b82e5fbff3b6bab544a162e9f3f86d6d62d6686577f7ce14b903a90330042f042ea21a84d16a70dc04d053f7b9338638895c6da489b3f5bc2384c9a4db437731897491155b5bd2fbb789e3481c74978cb113b1a14eeb72f7d9c57adaa6e167f0f2631c57dec50e5879ffdfc91049ab23ba96ffe9cd9e62e74be9ea91b2b30f2e96d5324817a97134e44a7635644dad5ff2a7373de9517efb17fde84dfee4e7c97bd4e79aab4bd49974adeda46bed0d85d4cd1063251dc9d495bad9fd76cbe2956ce99a289d94ad9549d7da2351684398a4a46be500818c33b791a7ced4953a95f708f0ecf6d5a65d6fb7c3dce599b106e7f65fb1582cd6ac61a935e18839fe43317aa29baca15daddb5d6a981e7d39044df7c6ddaefed5be9c2a33e68de9bd163d97bb7b96411622079152ced82f6ba409ead35a6badb5d6a7b535e3ad5c3647378d2e844e1badb5107a14daf97508a594d26929a5745a4a299d954e5b2bddaf43fc71fab771fa7f9bd1de7ef4ecdb7aa0cc42164bc71caa8d3ad677dcd32317767bd7aa3b72a5239da07fb7a24e0ed0a26c68dbacbc27ad6f240107811b9b67f70370b83cd1c621195ac3a101bca76df7341749f08a3e248d1cedcce3359751d334784579bfa7d53bc3eea8236b6af4fe544faa4a83b54016c802e1541af545aea2c71f21d772b49c298d91da80945abaebb6b686a7a1a5ada5d1da69ebb531a489288d51a3fb6df0469b6e9286a31ea22e3f0cedac83d6accd94c2e01ea16d43987b7857bb65a9b5d66e1c19c21d8b664ae9b5165fafc61adebb2a33ecbefb7637de7bb9a2dbbef737b1bfb2bcc3963eb2ca0b5ef4e4c78814461d56c6b87a148210892390484449389bb9f3f0e12e972bba5c3647ebe0b88dbcb9596d2979c478c4628c31c638b356eb6ddb7bb562cd9c87bbc86dadd633582b6756c698ebe686c55aadf66e02063ca6c90c83222ed866b8c361c479b88db72c8f9b1b166bb5da7b369b75c07b1c41f07cc7bb6d1a7792fe8ed70b309bcd6647a840c6660800497f2360ed7c39578c00dd07ed9b6eb7d4da77afeeeeb6d33404027a19a4f2ffe98d80cbd3a7794ae77f8cd087fe7fceffa774ceb97170eb53a7f6e39c74d2980f930234d6c5e7bfbbcf774e4a77ff399fd2f828f839ff6da03f3b38210f3aeea741803459335d7baab707c9a039f186570f5a636ff681582f57f12457f2dffd69849b3e49f894beab46b96907b992112d3794e12f57b1478e71baf4017cdd2e2b7743feaec17a32ee3ee90de99ed3288b64a86ad928dd79d02d9647fd083a7a08ef7ab76d8a46fe135fed3c681b038a2dadf4a926595229f268539dd6fa69be0daba77edfc7bd01ddd65f4c0b3c2412a9f4c9641f8f9d96161cf4a9d45bebbd66665aa699273f998c059b1a9a98546aab9040012473176b6d135c6d61bb00638516346de5858b19166c6a68624e9c6069b157b0e038ae0556a75d313215c6b6a9a189817172b2b54081b182052b2525e5f4c20577127432f38142f96862a6f2c9642c7427dfb7828c46339373ae3191c5cccc98929c36167732fb29299125df4c77f27d3232322cae254665b14a25938c7573336d6a686266342dd44234b3426634da2c16ac146d92d5980a575e8666e6b6c02b58e42cf3c7ea4ebe2fe6937d9f4cc66231fab45cf1c93ed927fb662a8b25d39d7c35a6c6509817152ab8ac52b4a050a53a6eb39c5841a9a4a06c272625275389a447a29096f135c9a8c4e13962ea8b1914e1f2f1f101811022788a142992815a6bad95524aa9af5e5844f81da37c29e99c52bae6d1ee73b212397aaac466dd32332a58c0c4ac5c5e5229b815aaaa42c76a41c162b1a27229bb858b403fa99a4a7dda962215c318b6c44c6a2ad56519884ca9974d22ed989b64305c8c11d3c3c170304696d9ca95545450a61fd3ccd4638a99784c3f4c58584c56b46bf473e2c44ccbc9d62c2ec674e548a452a9643a99b40ca7e20a4a49b9df6fdb2749719caddce8c56595824b6d1b8a0a458bb5a92ec72a6bcfc8a860e57c8a8149bdb8ac52702525262a142211abe564341bcd38125499edb24ac1c990482519158a169369140393c2783b7951d1d18f3bd9082dc555a1c0ab1e825a4c5ab854e5f268d6a369299e3a0303baca59afab389f22038d9a4ab5b46c9517142aa8a0325d5629b854ce5a4ad5b5a0c83248715b8a7628d5997eac7c97227555285aba139eca7110c2d40e7ee5bc8533fd4061ad4692aa9cac5caca954d79df054affbcdb282524941d94e4c489ab5a51861f59252a739248e9a839b34347812b28f142a79007062a59715eb2648140ae523946623279b3c69bda144cde61bc01c0b9978e0ee9de509a233101a3560e819b560dd6424f48cdc93816420d377eee1743a9548d4b695949498c4937e77f777eb9f87c82524afd7ebf57abd5eafd7ebf57abd5eafd7ebf57abdf0873ffce10f7ff8c31ffe5ef8c31ffef0873ffce1ef853ffce10f7ff8c3df0b7ff8c31ffef0f7c21ffef087bf17fef087bf17fef0873f5a69a5b9071db7dc73c7d051c7bbbb7f8ec93c446409815d66e31783903862d41c77893b03c9a952da00ced8cd5801771f8207180c0683c16030180c0683c16030180c0683c1601776611776613b3b3b3b3b3b3b4460371381dd4ce46622b167d239eb769933c4fcf9f3211108638410baa5f3fd0493d29f93be68f1a2429da24bbdbbde7aebb535aa36dcac1cbbe1b6263980414b6c47ac006d6aa0584ebb784132480605c1edf1074fee968927770db7893f3a117edfcfa7e3d271e9b8a48e8e8e8e01e28fdb48e9bbb5b74deb1f3a3f747e04fd700219e42e72dba0209917248396f8217ffc803140d46541d839927383968306741cd9a1638fec70fdff9c417f011d3a5a309fe035f8f9e1f92d88085f949343849c431925e4a0a48190888c71669f8918a3944772823e074889b823881d40bc4daea48f28fde71123f65a6b8f009152de8b33c63e485ca0775e043e4876344d7b2438586b6d28e4e3475228c208233d1af5088141101d1e234e30a28426695d7bace6432a91483a062553a9f443823821e8c4833e4646603a994c3b3e4690e073e4064f1af1c0a9e474fa9e77fdb719b14089494909904f111ff8cffaf830c1e4c4c4e4c811663e30994ca69393201b5a2216810425050545f3f1794149488a4a4acafd3cf9a614a8a05454340f162972c48b9a1542841c86080108140ffa10d101d40a2af4803885c8411826768600e1f2dc4d7cf09c891c1f1f0f7844e0b0726265c567891f1d48be679f9a7082e5c489ec412130c811c2938317c2669131218cdc426290c362c287901d7ae0c5adf920f1e3e313b33b58595959d9dba4042c2c2c2c1ce77344c7db388ee3bace67899df7e9610154494181323a2207391b55e6f9c69116aaa4114e015ce41620938031be98b6a2ab628a27c68f31768c25c611e329e8b08120166e4cbb16d2da6b379db5a9e9a0859ec6fc83103c7040881daaac3ef1c5b7720bd8fe6febb4b1db56e9d4de6b2b9533875aef91544698c4b5d5d66c030de5ca56285731e6233cc8ffbbcf7c049dd5adf5caa3f3fe2f33e55036efe44dbc126ff4804a4f5ea61ae54c5ec9cb56a31cc9cb57a39cf6465ed6445ec8cb218d729a97451ae5b297471ae5b0974994bb5e2669349b34ca512f9f728966924fb42daba4a488e2865502944e60d628679dfe4e43e0ee79c80d0030ab5beb32ca579c3737ee3f5fa585aa684b0a4ac6dabd17673c6ad19a34ca396b216d44b9e9b5684d1a8542a15068dbb6d153fa454889e521a8ff7d1f85ea546650dab560b1542a15e5e8a49b86b24c4451984aa651cbe954626262928d4081da2e42d19580e84ac614b9a3b6cd7da451a51da2283a3589442a994a233a8a9144f9062a914a242a517b31c6a7d3a9049e5c2402ca41ac3cea4d46d08da228e8a5a06c272625275389a447a29096f1b5372f70e69c3954267743c60100b47d8467b9bb28f4c24834e2e4bd5734ca398b462138caa2d148241289b210199a48c32119a22bd24ab413fd872e5a28f482e6693a4a8c422277f711a59ad5241249341a8224ca3810652025bb6332994423511ee234daa291a8563f019949d03a3f6e496bd5ff2e81e071adffa428799a3570bd68e095521a1070e7fd7b3de7755df7ca1e5e392ed7bd31e7755d0f6fe4a11561a65d305c5821868b1735362cccd0c4b4c0f156d41b9916582c5a88e169d60c8bf5c9be197c33f882e0f9e103898f249b61c1a686260606ccc909ccd60205c60a168b941499f2b9e0628c17312e623ed98faf8999ca2793a548b13ae59c5ca69f99e98b0179e1797129bd54d03c54a850e1022b269e636deb599680e99c74524ae99cb4d26971c0018728c0ff7faae3c12d733cbb63c70ed7b10c614d74a19dbecbc88139813cb7ef0aa9ffa4ddbbd073ff73393eca1e2094117a3b64286ba447d9595944ce1fa4a3dcf1851e4c0fbae6fefe2f9353c2901c6d1a4af7dd45e94e654e018e9cd6ec41c7ed312801d27f4aba33a41052e8124a9963c658647bd3ddbd6bcdf973d26e3e843a1c84b06b4138a17c086313352f7205ad5bb98227944af323a2b5efbeabbbcc1776bfad6eedae3f77abeefad7ce6bb7db4ecbd5db69a9b5707ed7da50fe4ac86eefdd208cddb4fb1d6f3737de19d3cbb9756c6bbdd28dc8a1e3fd9e5c6b12a1e39e362090f77f735f42b0498042d7d236a49ab6f3c69135665dd8d9c6a4d8eaff0df37fc6f0da0aa9adee72691250888c30b6822ce37332c6edf94b013897e3a3a76007ea00635804a6c186b1d168180fe28b2fc6185f08a3cb2a37ad76ad5a6bad706bb66b6d3270b41b475e6c3b0861249e36e08f87f1cbd58510c2a9e1c65d0be37de3d69b077d439f30c7fc43862af716eeee2cb982d7762d95efeb427fe7dbbabbefbfdde6af3db7fbceddb2f65a5bb56b5de8777fee4f70df6d5bf7da7b2db5a1557be9f60defdca8bae1dd2d77f75867aba3dbe99e74474a69f749f2772363f5ac629b67fba17d440877ec5a93c2980b34524d033ace24374db02691172d5edc350de808b78d763bbe53ea94562b6d6dbd17734c1c515e23f2ef08e54ab7346f6e7aedf51b6bfc39f7cfceb5dc41862f6887db06dae30e79f6d030c61867b28b5ac71bf20fa4b511f631cfe3dc5a0fcc3288c60d655e0c7235654f8f5c390c3168cf5bba237205042d65b227fff498797e71ad2f20f00c1ec49973d7ee86c389f1ee58c3bcc191ab1bcf6f368b852fe48edd0b4e7a0d90fb855c7987e342bf073996a4f18d6fdc6f7445a9fcc5e62dfcc59b49ea93a1ea7f43df316eb9d2170852c538040279d4dd210bf70e403bb6b3ea11b556eb4d7230581abb6eaaed56ddb2838173a1edaebb7634e48aeed8c520579452ba63a0216ba0dc38d2daade5be79216daccbe572c56250d6760ba1bbbb8b3ce835a0a6be510a370d060843f71ca2bf034286df77db8081b831bd168b67edaeb6e61f0d81dcef0f7286a1195c03a4efae35f78de8c91dff0219aa5428cfb66e6a4bb30fb3ef971956b65b41d7e49181000a3246b9a3dc0d8831c618a53b0cb118e11f40861a38bffd7f7b381247ea04e14f97906d9e57e933e7ea4e29f950fa11f67cf5618c94ee3ce9f6990fa8e4ad5dc68e460208021223170000180c0805c421912448c25096e30314001051685478624a94ca83518ee2308aa1208631c420050831c618c20c0d4d1d027218b3afcb510ba79a94fba8561bccfa952986d9976eeffbad853a266fb0a0a91014ade7d007186e55848f3e4ee9d17ad923bd2cc26609568f7b153f261c8924c30018edbf4939d846665ac18b4aee0f47b39b4b87bfcb4c4c79cf52cff24daaf4422ad28b6b6aa5e21e35e1a755615a868a3c583ba7993551eaa93e2a3deaddd485f4caec9a9bba91d81524e99add294b211d7c7d775bea5cf12399b4b93eb3eb685288318e433aef84147528bbb0c4782f39f5036c497268ede55d166f0b60687f4ebea3d9c1806f6db739ed2a976fe3c534b39b34c4d40271aabc1c3bd57ed277f703eda5ccacb7513dc8db73cd52d19fd1cc58f3667114e2707ca2a0d6d1e948bc5a76f0d16c2871faaf3b37f3134110127590aadf7f95e7e21274a68656f1c60038b4d940ff481895dd074e261495ecc16272096cce1a8f3a7c9acb7a3556d9f9f270f816caf95ba427c1c4ccefeafcbcab2308e09f89875d130afd20336039668e8994babf57945811d9101cc05fb1c04eaccbc3a4363d676856568f8b500da640bf12b3d9e934f68ae24b0bc783dbd84d8d39dfb077e19d4c9f54c0b33ad56e2517b6a078e23081d124c3cb3b154f88c61f66bf92f71aa27954932cf1acb1169f03bedeee5db38bb917c0ae3933ad340b33722598d802a745b2aed17d41caaf8fed5dc54428c405edf159f48b11126f454d65718d742ebb4c86be07ce75e21ee65221c0323c312f8b896b1c4a363f9a30a711d79840ebb5dd0cd7e29d4422045eae7d69ada14c93ea19078918a186a97942cba2416d3598ff772ff84c0ba5b36ee0306221c0c6ed72cb5b819d9e33312494629c85574ab1fef5314d3c7188dda196ab3392405a7a1e85019b7f10f32227563a83d225dde21be3c1db2fd090ddc7ff7d8038ecb152aedae5ac0974f34824b03288ccda63d9ed91119cb9a261ed92e678e3041b34d4868e7c6d956c104a41191bcf790c0f483fb5bde14c16a49f540a985de3a63246b10756ef2746811712ea3cb0545e5e0253269d3b53086f949cb5ab032afec9ccfdaeedece0442bc30f998fd5d8d63a0f47be252f60faac04be9468c8bdd1ca8043aff8bb5c1572444dd1be9da20fed4c12516dc210db35d2798d15003679e56e3ea2b35c3d77f8bfa00a8f612a2edfcd6ad8b91c6bc1b8c36d551d3ad309b6c6c16b40e3d0ffb3831115a2ab0e2fb18b397e5a5b78649b3e44ae29ca18156ed5454f89f10586a546c2d26c62a4f2afeb64d2fe88942084470ca0c890ef4d8a4b5c782258e7d04c547682de89814c7d38376528674521b20b8224694ae39c1ec1e6292c29855964d3b510985e52de6c4b7c620a1551ad34fe89099dc15f51037e65c8b931d0d61a5d36c38516354d0a3f067e33b99407b27ea9da47cd0cc8b913f021e490e05fac1304a8a67cdd5a0cee79927416fb0a0ab7ed570521aa5c375a90a7608cbce691648f32f1cc5cbe4be74288cd2ad8216bb7304197b363eef5adae8650b568b361b81b2db0414cd4ddebb6469432eec2d8e933aa79070e07dfc5d9794cbd1df9b60cbf1788d4ab6d08702ee238103d824b15e2fed6bd538c66353ed5021efa99a9289c493903011833a24f032be77b586548992628dd9191fc1ad2cad1da08f0d641a1d345eb25f779decf1e7d80377daf6e86e29efd5e1bb4f25bccc97910cd2ac8a738e11aa927c2c515bee1495afdb590aca5423da57a5522daf0244b268576c9a0549e96023b7becc244bfb5710f04b236b14bc901570292e3cef0ca7c3144ef28d11afc9926d042572890892e8df6244f90fc2ab00238fe68d92b6fc105b51b1c9130ca693cff3322527d4c4727650be32a5e55b698ead62c801d8e58e6b1f32f815443a284736177c617ef0464d0bd136aa1a4ea7782dc42734e136b2305978fd886bc9d113c0992c3f08a97708a3171ebac0e755f191254ac0aecfa29ba579bb31777a7101b3e7d67aa9d2db95d9e8adb3b55c66d4e1b5cef6d4b2eacdafa0ce6a605445d677b46e1e3297c43a530d62fa213015cb437bcbaa723a8a3b0ca10add1b8eb9811c9ddbb8f7abe9aa5ad5d682b8b7c4ad1431e90b573b5b8c37512e10cbab69d8593f3e32c34f8665cf35d0f839eac96230b06bf1cca7445554002af0b5130028d22063323382a5942d7b59062f83faf934537e192a0105cd8a49b0002be3d1e1082e2199b3384b8563ae7308810b2d41596ad10de4ada7f2c582de54ea38915f5d484838810b5ac2b49089a3c84f54a68ae91fcb12d9cbfc3ea075c1de799743996a845cd89047a0573e16c307a5ba40df59fcb7a94040cfcd104cbbab887f4297b5c4d73e1452e6dc78a0e694b24527aa6d5b748ac483702fbd82354cf480ed80bc05cb5220c0984ad41107557396ae539f7b0fd462df51c103c214cdcaff376031bb3c48ced84d7d7a57925a9845f80cc0172b38d3f7597e3e106b1aca40343ef740ff986953ee42570d9bd17b39cc3599f10cd1971376e9be3c1240d11f9ccd74d90a561caaef84883a31177519a82434d10e38378b5349841c4518c607db0de32b133bd8323cd697bd044209b09457571f813b67b32d3e14f644a3c65a4291b146976581f2c20bd15d30168df83c80768d6510273c4e7972001ac01967633926de491ccbd7ca888ccfc719ab1752c091644028229548eeb93553b4e3b9df5f872e779a583a21d20533b3a41db92ad8da552ba0bf069c61d9566ec552a5f0849b6544889d262435777566e73a25eb5a94f26ad3625d2f1b04151a2381e64359944dc6a80bad5978aae48634cc4dbad9ff0f5611b449cd920b595c5ee68016ab4cb6ef7c87a175965294eeb72190aac38b114d0e2e0d9ce2cfbf22d4c9a9302988d41b6e42d2888fe02214348eb15d1f91527d0c1fc0ac3902a108016b4907d765b03cc5420a6cd34882ea83eeb8024662f7f831e2c37851bf930c356941057177a99d7d5e52e7c930ecd3f046a989d4a402f6a53ae6bad0089d495c263cceccd8b164ad5fc0862f2d3cd1279539846a034a14474b1102e7cc0633308d2fcd40ca4ee6832bd70e8c5beaf2bbb836c077ba556d532b3eee601779a5ef8cea37a08f2a3c294b5cfc8a5f3855ac1b2a05ce293acb2f3b451d18ca431df1066f1eae945bc70ff6fa389aed0079ac864e73d73899426acb445428320039d438b3c6dd163fd70d6b4d8eee31acb76e43b3c0e41b8c9eb9ba1f92f27534638869ac76eb122e498ac43e3507df39c7fd66b1fd1a744a38dbffe1e7977995cb9e7c97ca01bf7b5253f1bc6ede041335503b4ade3b900303842ff0a2e55aeb1304eaa234db3827d5be6c3d4d8501554d971050d165ff4270a2b34e63351443014ea50980d2289d79fc832a2931603d333cd2f76c09b707284564f89748663fd8983a86d6ab7e274245f91f61fb709be02839538e2f75af261f36e88bbb40df0d4e431a8da52495fda6b39ad6962230593a3133fa3e380cedabadd258dcb462ef36727d27f3deddf78deeb50189c23eb68c82c31ab0acc136c413515eef35dd02ee312a3f4aa92217c9498fcfb17db66ec996c96016b9c070468d4326ac1dd7c6a716ec8ac7685145ada3829979436715867c17e7ea01c2e1ca8ca81134eafd50964fe4e950c508d87b506f28cd33a0e4633aea1848a0c5d56fee8880fa844261633ebf62e6e8e9a22954b2d3e720acb880cd2f9d2b43ee6a775f9897188832522b3c946d56ebe0bea34908b9cbdec18206a3b9ec26f487b31af358ae7b5bc4406e994034f24dccfbed58ea35d6254b64969722b341d392ab54535dd352c920e764d8b5892a88a4ace5bf892f2f9028b8b94ee2e523b5d13436ee5a4f8375566818bf9cae4a46200c66b918e117311ad98bdb716b5cb8eefc8a9bbe7488d7050cdc3a81f586666db21bef5aed94e7c4fb17bc18d07a02d25db99ea8e5a24137c35b5806db40d4828ce300d602ab0acbf09fd8678cd484e2f60d70be61ebaf8427fe7647ec953e9d9b8c7133199ed1e555b43bb7ac31ce2f19d155715a7230802e02a758bd3e75071e85e0800abeeb862361ed267bf81e11ecbb3b96e9cd448aae4d26509930807725968767d80e8974c323fcdb237c98e23ab84e86534d436a42797ba5260df51f2854beb3c2de35effcfb673cc7454ea985d41560248c693e6aaf92d12b5e97f2b8124d65f5c71055ade217ed5ca94bfeb724c65f245f30d68e0335facad2e95edd2f6bc6b5043fdde1b12af8a33ce0c79eab88e4bb52710c5d745b8ed26a5319cc31a4b2194a868fe47d8e938691a31bf11612ebde8f6a3faf9d4afd28e751c09bc491c212d1804b93e62a9dd24c5c03fa6c11de4be1b4a92defeb158081d4a8e36a63fc8b9828d1884059d4a5813a42dd2c050ab5a4a0a90949c03464669111ca728190ee861a3b450a7d3583e4f99bf1472ffc650b3a8eacb6e29c6fb32763e8ed2591387551c1fe082c51cc5c161a58c503b23298562eb1296611d418cd20c9ab2b4610f491178f2b4db20fc77f18d03af1b57d4a0e23829dae04b844b8271b87b4e46f057566b17850dc45ce1b6c3f6ccac87702ff7feb95d869f745fcd50c4f86187facd1245442e205784cc84eac9b972c3e8ad0737f9d7773d2d6623172255d6347499601dba127605bb1362c7cbc46647d2689fe8534c67794481a91a77a103ba0f914d5b5e9eadd9b27e85b39a27a2d80bfd68988b078982862ed9420aec87d71978e5004502eec3c88cf9eac695046500d2fc78593a2620f210776ef5d53ca67fc55338df4f145e30a33dbcf8ef0545126fc32e2dcb0f3a128b54fba944746a625f248ec12d91d8897424d38c7c0cbd7a89cda21a54e44d4d8a6b2f50b57819052ae549064f9a79ea829a63724a6ae17fdd773c114e87c7a5f2d12a0be163ab2c25d25896b110a503a7f34650bc04e375578a27cbd97f76c45e024cb7287e9493b814a4f67db5a8c4223f5a34eb864be1549d34d82de57cda30ceb7717d2d7aed9601811d83452fc673bd1474e54b605f90fea7850b1846d1c22b5e0ff7f283161d8fd482269dee8a603402c4fa841aceac23962d236e4ab58e212ba76c6827e03b11483c3d00f5874b90f011f87b4aeaac737bf7e977a018f13ef5b65f50101f7d73eb1c3604dccf7360c8b08fb64dcbf036670e02a9eae30b4844f393e391a64fdc0c88fd2835aaecf696d0cbb5bd05f888228fe284419f49496b8bf85795bab7136eb1abe0918054d7d32e8b288b5f780c14e03a232f83aee4f550557b12a7891c5dc064f2d1375c9d6d604bb99853482f4440b63421e9ead284f6597c2bb4db1e70cd8ebae5321237c46f4aba4b5b1b16ce642e6151b2b0c929746310664dc0501b20fd9d64c6ea930296273966dfbd24625f1dd40c52e6e80f14eb45fa56a6c40f81d3de38ddb231a25fc0842097c320b7534fc30470692d7ba09747c370b20787d35f296887d8901502c825bd5c5d43b556b8380a4a1b24d8133d634dab12d3a5d106f32e40d7bba1e1d7b2dd3810c102c0247b528cd0d0e774229f35095495b2d556088e70ec4a079ab46629edc9dfbe98c6bf05b97736935eb0abc402752b16f8b7659a1d63f4015895e6086aa25216a380f0e37e29aab37c40ec5a9afe97126353f5814d14e9d62ab1b84e92f946ea54f42c937add2d8608022381299c8b48fcfb69ad74dfb5c5beefd80ec57f4251f6eda02b2048ea06e388199602ba20f11b1e94cb31d0de8b3150572b0fecaf8203baeb398203b2724f667bfb9bdc99b05ac4760a7c669c0a9de098f5b25aede69d7d19ba2ffaef0e5de78ebdd976e59279c7645404eadf19d9f76b9be69d41f64a31948018211915433181f2ebaab82e2a2c2a03fb65ddc4c9fca3c4c11c435f98ef8eae05778c29f255852b50ec500a6955056714398c694ede82dc0e9f6427779f2777ad102937713f93289873ed7172df6b2128c9a0c74ca31d841c30e3fa2b5000f69684da469888b849acbde2fbc8dc0650a7f8f8d5eb213c7653337d4bce05ab3c6867ac40f424870ef64e03e7739be96b8b40c35c97d893307b86e87fb529790314bcb1416ac5e4b41b33b920c53308dc562264397c2c889f3ed59c14f38bf01c3e261b3967bf7e67ff19a462fbfc357cc6749efca173b47378deb9cf978d9d1f3ffd7e7f1339fcd9db8d5e96be1810cc4a50bc228838f9075f2148092a34257f9582bddb11c8c2fa68313d0fbae40c02b940775aeb028378f202060c5c0241d0388c1725d010b4088e8ce90a27271cb3c98224a6734e99cbe75120085266c72196772bd38b87152bb300c9a476f580421f0588457b7fb3186c08c4e2ed40723c5f707f8640b9b8173333e4586579131510bd6f07e3d46bc5969edc1b113c8b964dda77f5a9105effc2612dce8b596aa6cea9306624ded5001948a77209579ae83f937bf0bba805d3ad12592af4cbca6ecb04e94345e8e7af8be785cd66df222bbcf3eaad7704351034fc3a6d4a0662f1af6796ed5e208cd23124be0e8e6ecfa2bef6c79333f1aaf897359ffc07c91933c971533dac357591bc81c2eed12c0715ce570bd3cb075a23a16d646ac2736206bb6797c3fd17f7c6660f8cc0b2745519ed6f6af2633b87adb05733404f6a18266af374fcbe0c060f0408c33f36ef02590253f6f623876ef75407ebe43d0273bc94a8a30e321ac6da0c1d373f08d84ea065bb9316e413894b2bf1942196472a46afc4d76bd40a67fd9d1c04d32de9cc86fa0702badd284179e588930fc1ca2b3e341176993c30a4a5080e077fcb101c80798243deecfd00ff58918e541552a17a6c7f7d997014035f9d6aed054a024ba2be7892a35f91165569f71ee09fcbaab0d88837b9df84d9fd6c327dc1acc325405ecde3d962302f9d43a5a4203778fccdd5707c36185ed80854e75effee79d65136a14aa08985a86bb681ebd912eb1b617f1491b050a3f436eafdaca22b1db17b28548d25d6df8f1159b05931cb65400f316510a2f15afa142686ff7e26b9e6c986edb91b796a73ad8cc0e4be495bcfef74f273891c34a18e23e2e6a219be8171049a512a8b416eb9ca17bb833ca1b1b9b0c797ff9d43a226bf2726afab70d81239fcbccb401a9799e3038e1a9426af1df3433843035ae318c96fad6f70d569f2a04d3049020e19218d21c631436a49dd4cfb2f68228358c1d9de4b1d476cfcee7bb26a68fc62f107a47b1356a91a64eb049f970658335c7c2034caf1cd84f4cab5635d17929caac8c429b0986a10a83d891ad530d1d4d0c4bd31b0c086420a22ab6d06ab825c20e140939260fdc0c5a1c6e228a3718739661d0034003a6d9e81403c0f4e2e350848dddeef240d5429614a0d2d0d48a69c2ea4f97c2ea57414ff0547ed305e48b536028d86d40c2816aba42a8238881a5ad2c0ea02b7d5221dd4605c3f2bf0407f988f111718bab33e6e769069b849a1c7e9be89cc74d1e9fc2383ee90fad451a0f39406912404c488bcfd1a7666dfac21f11dd3db10d883a8a4b153155d2819b5ce4a68ae0130c409a2b9569a1eb53f1df9527af0778a1887401969e82acefb7e99ad72684983d2c7b312c289c7a2150d3d00170914ab1c69e8064b3b5a07dcff96e89a22a55f2f3a480395217e3caef49ce9f933411ae272eefc0969f6d4154f9b23ef7b0ca8765e1c3c1a045cc61a3ffcfa433070b739b836de454ca4c3762e08ec224a075dcf49ba08b186973a4d512c0f1d859960bea4cc0500117d7cc2635b875c045b0f908c1134bd6e3a1d4c18cc041d2328a4004342643d20df227253439b0e4384232191b812404a618bd5076b61f105c0c5c194261f4712bc058d926c6d7308063e038028a1f5102c4beb0b33e15ef1cb18e3aa46fdfac11d008970d9f90f3c767dfbed558a1371f145d2fcff1e5c4378817372b8c8e0ef042ac25b4887a9d2e6f0a93f0b4c3bc842b65e6acba2a7b2c2dfdac0ee6c6df16d9426fa8e6778f217f267ca12469105ee7aec6efadd678627245c9df6b3fb44c0e197a786918ac0390575062df7b88d3ff00835389d21f49e9e56da0f33dd0fac32cdfc707bc52dabb87392b56048364a8a8acb76eaae92223666a1f2c30238b426ffb0d639b23a12073ab4f7d01727bb0f4519f2830529695aeee2878f460ac1a30efca0757e8ca227152e83d5013c51b91d41c39d2afa50689dc4343603125820eeba21075441efa5d80235ee60eabf4c497b55474caee417cd64de3c18f609104f4448e246b333b10ff2429b631f44971a803dfbdd9752b07a7d24100275cdf8b3bb75100e7d30fc80d06a249392f3a11596d5392ef3a1f9cfef0ec94d70d387161db1037fd9fe5b905ef5c43e14a228af9472567ae8837f503b6fea8e87e6c339c7d5b32aab552fe23e05d27bed3abd5aa9650992453d7653485eff80fbef2709106ef4c8e01d4325a3030ac4953c7c28762946cac0124c046a525e2502502dd4fab1b2a244850f6a93ec268221066a29fa1f1d807bed9e00b3ff7be808a369216432d704a2f27bd009f5763f375d3556a0a5212a02ef07c90905f217821888baf496690933fc18eabd072a0eaeb8247c4e0b5aed6f8bde0348fce9c1aee5de975d3342f0e29b02fcbbc8bbe1086b018a7b10046d42c537788f6e18bc071e1c44194a154115036154314c38cbde4f95383a47a865a3227ff36a797b18c4cca8f282e15ddeec35fd88d634d3a56163f884a8570d58262f3a1d995d4d9743bb2c860fa889b43cf9801f7fb607b24f0b2e525718c2e1247d7b2f9edab7aef580166d564aa8225f6a72463b47eb8de9da430ff1eb17a506505ee783428cafa4d57c18dbbfd1d70799fa563e581679e08afc72b4fe539269d5e44c93d892ec83889744cb1b5762744313373924a217432ffdc83795d06a391a3e10936a0135b91de07a0d1fd0d75922276757f361c3872bafaeea1bfe602152379fef87399b03c2a6ed1ee2088a077532b3a3d34550661019ac8f7b88d27609c90eee7e5c0a71e3f670993230b5aebaf740cd8c9845fdd5f65fd6d99724fcaff57c3304448d760f0be3392f07f669e21eeee505afdf1e72e8f8e7b83d749acff7cac9b6c0d0bc6b08fa0ae7f5a84faae3bc544a4583801a1b73be0330f4b6d743069d672e3b0c27b985c91e789101a1e1ed87dfca9b973d0402629222c15d44f49e50d78756879fc2f3fa640907010ab9fc2af6007f4a89d879a648b46c17260c43e79c5d39e67eb25388bb8826ec016971d6953e72ff7a08bc34ac69247803a018c0fee4eee02a840a1533457eb0fe033ef3d743dcf27e3293c5cdc27559bdefba1e4cd9e4460acda724ebe158105fcfec1ef540bb2fca797b04894b9b86582749ed68654f37d85a7f58e5e1655c1f88fc828c2da0871926bab650f2b780a81991ef80a2ee45e8984c5b92171e3b097e1c7381b0b05fa0d58a0f3d019ffe44b85b641a4162a9726be70f5aec9ad831b5e88ca28f9149669049246e3a22a30480811e38f9e4a9d40a962e9b9abc5802789fb24e10239099a0e19b6d77d69da287ed57a80a8ef7d705c9285108b92ea80be0f685c0b2f7c360f8206c6668e704da58866708974b9b81e8360ecb40e8c8d52c72281ac056068ece44845139033aaf10369b420334035673c0c2582250db1faa42c3f4385610de6bdd5f0aaac35e1d3cd33bde97cc7b48aa222d6007b1422f0eff04cfd4672069f8b7853bd4d33b089e099753ce68ba653b0583ed77896eb41f2c45690de77338e8d9431b8bf0ec81fc6dbb820cc4f925576e843c5438035797985f5956078107b97f4642461da67492eaf35ea38892141da9800c385bfec48234070275ee086a94446d16c30f8d4fb4e91142cdc6b9cc58015d7b709dd153b3cfe838dc922c723bd54b013d35e1598a1ab3a57443c1b9f9cc6d62b7c9af4ef439e2ee34c1ca0609a9df4ba68c1b202a731fe536dd65c56d8187618203bc0869296ab938d346890fe941a002e94c06ccd6a9c8c3ca934a600804374c7649284ec3fca705ed5f8494111b667b7c0a0833457d72f891ad2491851a0c071d141507aa8899ebb524fa1cad20e69051cfbd8a8348845c061e5172dd01435dfcf2758ebe421f0d09609baae7913a24302ae8ff37ca8c7cc0913f483755e581d0e74288074598f9d60aabfa2da25961cdb9386c5e67ee882bf76c03f0bb41793f4852f877751d96476a6c33445e1f57d03e98021b6b8fd7f7c36936f712427ae30dd18b64279c38ce9547d00175952ed97b1242da636155d9e009db75e0dc2d675b0d7c349d174dc19f595e6d2437f33980b6d754a25bb94e76706bda4083a119901ed889750125f99da1f80c4fc39510a2428ccdfbab207a81b4f1e1b2f4ae7ea75a2f30c90fc764540b0a8b229533d5bcd960ef5da444410888bf26965721f02045a0cff67181b32c0396eadf9b72a67bc7a752fdc138d95b4048214e4810564487951320c07beee41327006a1173334782afec1383be4c9b72a1c62ec13b4f98f70ee55a074a1746d6f5ea3586f219f299e9326b29c122ae6e7ce2414eec97155a660dde98c96297b7a557f056d572bf9b4b4d260a74be67f5260994aa1ca4e398bbd58bf69d32323636a84e02a4e10faf1c8fc96c7110b060e2f5710126a2a22411e39008ae0c267dcb0d72bac1affbd3cc904c10d2fb550afb3b0677074b5432b800a017b2410ad00d80a09e873afd7a174d1fe3a4e555c0dfc76b90923119cf17f261d847c49dd2fc0747d9b170e42c2ca7e9ce1a24f3840b8ba6116b10ca7bf47632351c361c4fb08d841d05912eb6329b06ba6561f84bce6f7e245a6a80f21d7c6a9099c0f5f6711462208d47a91e0d8318bf53f144ccaf9fb3fd5b1290c61586824b5a106386b13875ffb27fef5bffeba6464f37b1d11dc9e47a1c048b3d90e813b800abebd7c07bd4f4d5f7666594436f918c80e51761ee63449088906748f5c769a90f073774d6a1bb6f7594de1821844462ec8c1110cf71201a65553fa88711b50eef9a8e6144f260c8f150822e4eed509072f76227c9f222de91d59e46a8b9b1b9b7606915e23486ca951caa448b2047f0ec01927fcdd0729adb6985f5e75b4e02c19eaf003e85d28ee624333c86c70b5234b4aebda799f2859b46349fbfdd45ecb62b0d722aa6d17626039cc58040ed335faeae8b80aa9c08381031339da2f131af08c04dfd3d9443c5ae417289ddfa5b4ba0818d3934c8b13f584bea13eeef09892401d97067f70703d01d08b5f045ecb3d0c0888dd242302f7f639158f50056e43f921a4c54d55bb5a61a35509652d69087edac7669430231f28c229f1f51a2dfb27f7b0ea20616521087bddf08d6a8ba253041fb4c7fb1df4ef44bf67eeb8fcdfff8b643be8e39bddf27c3749d868456711de054565aa1733c9d6f4259c6fa0af66f940de2bd5384e815c9cb6946bc0532cf226c2c848eaf6d99b9f65b322c142697b3e7df9ba0e9f4bdbc01479494ba3266998a7cae7db25044f5df0d14d154a9db060d3fffe20ce4e8152efb0d3871c5e41b4692b850794b95addf7581130f37d9ccaa7e736024f21aa462d6019c28e66306d5b269c0fb275226c76f2f56a0ca82f4157a161f850c6ad6ec2b6db455ebe31c7e2be9962efda6c1a0d5ffd71c914c2c7783e226c47bc341bfa5c0a7673ed1b3e659967042ffc017893d941101a036089989a194ec47e83ea40776625d408974c2a6cf817e57a463e16d94a45ca971895d8aad8b72c07588e063ee310e8072f75cef5c7cb1d7dee37ae80a12ab627e13d4d95b7a4d0179286dcbe44b0734559b8319d801e019f36496e7005ba4e7ca388e169071ba90df713517c386c4480aafa94c33d07a0977fc047d8554fa733aa0e068a255d7007bc3896a36800ec4663a98966736a5030abedde35b85df528c24a8896b358b6b5fa3c633d009ec6a23af83fab69beba08ca0cf446d1dc89935deac8321328bbfb00eae0cec9bb05f285c215f68a229ace139b0b5cda918f5b6e0be0d9e1129aee37fd4794e3976609d12805062071ff99955b003191909980393364f0b54834169a51798e4811ddd1332617d536d4c83c26506266ed278bce338f5fd645314b12893551bec921938003dfaa64d858b96bd9767d2ed448fb90514151b757c4bb2fe56f48468988c84d358d40df47d8a534aa3ef6b93d966c26a69c9e80753999971c47ccff749a9e31597ef923c98e27772a3f3ad693aff94ceb77c68f3498635645de73b0ed553e36943e77bad6384802e722acf77065a08396ce44cc22c624538b9f3df15a3e3302706eccbc27bf31d017d805857273318c1c9ac9258be8b36302c62738f852cdf41cbdc4a4d1fd827af1e1fe7033902a7f5fc97b62dc826af0de414ddd863e053c4078d347ca063d08390514038c5f79939ab0ad691850f9c42e01a45f04129df7173eaf18d3b3bcc15d1b058f87b608f3fdf03194ff790ffb96d8c61f0402aaab9295fc395c3ae74700f7c65f4316d0f107a1eacc90d361cf6bdafdc118d3b977e39c0bfaa8740327870f80f3b88ce157c1f488d3b5fbc998007826f68821541ee64d2ab4b3636a917446c7e077276acc2f863fa0fb1e5070d71ea68fadad28730a85946a31ddb6f11d1bc031e29a785b6c627bc833b339c15df075b295dd1eea0c663cbc3dc2e45450ac11d74d14887cf700fd97fb63bf4f784ceff1d3ba0fce7881dece57b930e7620d02080e0eba094746a3e7f9eb316e0f77b5c07dd66b8192f7a23f1f932b13a10bd6982d5200a3ed43d90711a58869a851a0b89c5ff6047261caf7a4956c2ae435d7ce9173685a374c860bfeb9fbaabffa7e806b69383663f04ebc973fdd84401c8dfd246e57ebd8faae69091a53896b877463213e20d25137f85dc3ec9b0289ef31fa92bf9e8811c049bbc868c806dc2b5c701bc790651fd0ae22d89741c98b624dc07954d4401696686295fa3913beeb4c842cc1540df5fb5f74402dbaf8c99ea363d03e341e92512315f5ad24ca05fd93c65eca8dfd4ccd806542ba157558b2abebcd9f60682db51c62e759b782e0c7521bdddc57e6b97d84870ff3c10130bc214a0d97a2382dbf72f261284f9bbb7b27ddcb157f2493d58ee7da98e0d99565b4d647f02b67c70b1165c8766adfa2740e864ec3cc8c76448be5479e05ab61ff276e11509cb4f78c239b905778c5cc96b222954f6f29554541a1ac63af1ec0ce480d29911040ef04ea684db329ebb4bc19d19d5e57e7a1039736c9a302b8d1674151bcdb21f48a21f1b1aac404521dd47bd53bee339f8bda505969620532dfa15cc710af82bf76c9243c8c1a649396cb847c0f19996a311d543ec8e3dd949e0cf8dbb3e4283f0cb2d0684fdac2566dc386085669d967e94a7646204a0bfb4e36de31404901b024da6ea30a38d1ba96816ddc6712c1b429ba671c4b477a49d87fb694638a24256145808845d69aa1177846e3fd3698aed226a013a472f88eb2bba0b933942814a5cf1be6982c29ffb3f8fe5b93b10afc208ce6eb124e3c2e0fb0bd7166f335e06c7bf30d52494f67c327502f5164d81cf6929f74df1dd465980cedb0fe27a6d57eac41d1be619834b5a16023c775dd32fc664fc077379e11be5c48638db10fa7a31109cd13680a1ec589f01633925dfa6c7266c7b4135e5304e29ad443c9c97a6bb4160ed6d5e53a536b1bb2b1ce34bf2f0cc62f236f5ba04ef307e9843d95544fd639ed054a54a4b5ac17774e13bd227bbb422a89bec407ca8336b1a1384b06b48a2edadc26eba48f39bacfac748c8521b840b0a6942d71413ff52bca6e09911850cba94cf1fa9716ad945a260bc7108f235620ddc49c15f16acc57481e1244df05415aea9946ec7b981683537b8931132baa323ddf89eadc211937821d18874d592f50a433bd2a51723842aa3589ffc52ec2b45530d958d8d6202892c786500dca95f11d969d875e8bfaa07637543d41aa847ac8c6e93564449f6dedee2d20550c44a082a99a72f1294ba92c0d5ddda8df198eb4b2ec7baf6e4bed8c36713eee70360014ce7573a96fed168fb4779fc47fc93971a24127000fd17a00eb07223183c73aadb68a88bd1c762acb41054d75204eee557cecc96802241a3ff1997a8d358b89f1520da52eb09f7366bb6ac6d104487c08a9f9ffb413746742b0467fb836a32d6973b70bfb0e6a9ac3f1777a773127f86caa7614292c3ba8800e80e29145e7affae0140911b462110876765934527bde87f59666db24f57c53d0936e8e299b6dfd9acd4cf33779548900d1378ebe883bda2e989ac2b40ec64cb0aded6f501ec6606c8c305c8cc9be3596a9d84dd8f0281b6b0ef3384552e4e3c5bcb31680fc5dc6712fa6461f3d0008b8f682c27d58384038e91c289c894078453a6f15885b5c1cbff8f728faec7fc50f64ab63f86113957b1bf0eecc582d406f3f82d1c7148650f8d9c886f2ca440a42759a3eb2aa495b6920ba1e48491ae56b42d2ec64b702bbb4acef5b1ae6431d272bc9e39fad4b510fbb539829efbc015fbea418cf24bbd0dfc12598953d473c58c911a4a9f8f561802a9890d99dc763f2087a26576fff82853046526dd7db940ab2291f70875e31b2019caacce59d7c4e0804633548847baecdf5a691b21a62c994fc5ecbe8e3965e4f157698b37f2adc9b21a577ded25e951152f97d31593b46ac2a7975bef896d290e7b9cc099049355a285111ca1ded0e84e543ecaf6eccf73da891855134c41b230e090b2b72519c42ba10b93dfd3ddc7906b86e07d5fb8cd2e21219f2b061a48e4f3651c2125ff07bba21f3bb431422b8043dfd0d13b31e85c3ea26d8406419ba1eba3a328d10c0e47180d943605631ee5b15b72a33747fcb744ca40c02cbf6b1990fcd825d6f41ce2e925beb7ae6ecbc3d34bc0fef65bfbaf56dad852013745bab42973aedd71310b6c9ce1b5ffe0ca2eb4edbebf36b26e15e1545e8998e19e06696a53d24ebcf037e64fa1c8c4a0d106e0b366ed890ecd422f382535b8b2461e42586ad338496bd8b0719ffa40cd649aabff4b04e70225611989705a5853685d53688b79dd473bae8cb876787f6f3f526efcf955b7ded041677b66414d8caa20fd0812d1f12f7ca8ab8720fc62393ddc49dba4308c5e784268fbe6dab9130ab87499610368a93a47d5497becf1703977072414186032a67287a917f71d11b206113432d7c866b031135ca5b55a62bee44a9b2e15e63d927cb6ca61d16cb31e3be456f830617b3df8c739adff71ebd06de11a82d9571d6b4e028423ea4e2fc6b18871f41a82c4fd9c5c5a51a38b3762bd97be53fcba63c12449fda69fcd0c91849534cdb15c824240f6da0a36b62efb26357bc22b32097ab23f7f25631d5a05d282a24ded29152baa79d53796e9a3fad8bebd1a43b5007e016bcfa63322e610c71d3ff47f46d892fa77571b180fe52fc73435c8388697aafbccf435073588b430358f723e4c4a65bb678ede5e0d181afe0f525bc5c65902c1b72381dde568dff127089c00670d2ab8893b6558d8b9b9b304678fcd969b56dd5bf9e6b317e7f3b4f3197248690f200a7f99caaf6b885bf027c7e509806e7a925800c943656408dec180968679a6072a54550c63880fb37455841cb02165b14893e7f6847d29039b662e5c5ba474463fd78700b41d08a9fa615b6134f58b610fd5f9a4cf1a5807abc945184407fd7d5bea858a61e4744d2ea5cd001b9fc65dea6b5fa106fb0f9d840c2fa9e80c824db710a1c5f7f5d71faf9072cc7ff1b9a230d02ec96ac5983b0fba62a04c92f27b88b6801a5b5986d81c861092089ded628182fb8dae391f0606068f70bf5616c0ad76b1606e83c47a3ffa1b09238946830b731852f8dbfe33d444022bbed90b680af17b0a7acaf38a96f63ee75d118d217bb36b00ec01edcd2ad6ec5143b25e615aea1bb6ed5464ca477d29cdfe761e929acddad9f86d6aab43c1e4202aec691467c0978ac5d75fe71974f4826e8bc0d756ed2ce354b2606bb2bfb47b590e3d59b2bc4790361b8b4062b911af6c0a50520d5a7fcd95fa837d728add9f0b81954c1ed2b5b3569626a0835888646658bfccfb4240c2415729168718d3da3b2d9f84b3a6d81008473ad81ac5e240a2da4e7c173c46e159d2e3468d3568966210b58eb28abe2e2f148bb380b9adc1759af8fab198907f19aa593524b9b1ae6d4996059add68807d59b04951b20d2306c02dd614d23d84c3b5135e7196b3a82be5cb676984c03d1ade927a9312e353d9805aa0cddfe809f6787cc31505e71b50ab89217a4039a4cef4d4f2896cd6dd37d910ad569aabe85691cd251b9b8c5392501a308e9ea796db4844809e8c9a981643f78ff95a16942c6275693ca0160312ee354c903b424510527cf0e2d92b927ac461da0a3f4ebb85ec3de145ca949336394ff6d07c8b02bbf2479c35a4f35a11270b9e5fae877b73e47ae28d2c41d0f7b543f64e26440f5972d022a0e7b1300cf93b817bfe776671c62f9b9f475438ab583fe5b30cf5c23ea24c9e159294ef94c3caabbc9c6811c9c805286214fb707055b101b5d73e271b616dd065781de3696eda9d92009823ecc26ea036ba3fd47e6eb1d5118187dcd4113a04ae6053328d10ab63f522d3db5635dd728fd5d71e3c60ca710a79f7b730f61f982a1dd734429f5b8d42168156e70e48ef85f5e1c75fb123ba4561577e91c373d8e788ca97e1ea94a4b22b83b928a6446b9d8d6d123ababee13a4443bfd31240e397c0250f26001b26f61382c7e8449770447041ff6181b543180f6641239916d6029569a6d738b79716508c99e46b189e55ee126767dbc24cfb411fa9f4c61a272c42c30af8740da1bf5f054ef42f86adf73709ebf2309ab9dbcfc0cb01736a233b154a9015b1038a9758bd4064f5e6a23f975f7ece5a06d81809bb9604c1569a8c806eadebef3985e5622f0b6a0972672bce077551056f07884b6ab8f92fa418dc8bd4c32816cf472b936c5d752d02f80bbf821d5fc3b7eb782b9cc26c61aac4af2dabe5902b0446a9c8feb9d8f679415c14581e27110fab6253bf517b174d2ec852e86a5dc8f5dc0a42f391766e46634d50eab9c5f6fd1a5f3af0b6ad8893f2d02aeb1a191571eb5748adfbc08010066ea57bdf31dfcf44ec4ae9c83d3b4f029f56b8e519e297874ff5c579714f67dfee940de72188baf273b9b0d3ed433d3694055559cc00f09ae1724287e91df889e39b7bbcda083c78ac59b370bf694dd060a2a3704d686c814c308d6a0200ec6bec2ae68d25468e3578286cb267aaafa56d9d47af380de0ea22778897a04100536a054ae1404f6efce7542a07b9bbce5d9bd1fdcdd1d1468c3b946cbc4c8969cc698c0484c442b2b19f831bb197631cc89b36947e38fd88124eed08764230ad441f767a4767cbefca81cd30c134717e79068f19ecd581d686334155f6d694027d2b2e2ba765120740331885883d2ade72840f153b089512d6b4161e3570903b474810167e194d832bdc6c9d8e58afe71c954506d2c37a6294ae08bfb92086b669fda6593b5a2dfd0b5af6144b91f2bcde272e8817504cd7c2d13591189be883084a83275914d2568123ad512b6fb413337e1407aa54fe0a6545fd90a37d81cdbd817b782dc0707f8f78189890ee1d0115949d32a08226b7359538bfeaede2c7fdc003db1c33935bae130b7f19fab6997c353f763965343135d0ca4bd1d5f855d571ab4ad367c7f19985606745a2a00ab0d1df05cd884c8f39b4dc2dd7bad490aa5bef6c7ea45bef0a0f63fade725951fa6b262fac7e16dc9d9080f0d56db9f22d631c58efe978636268e97844c8271b30002c93d2b43784e9dd28f4a952083f66ecb118f958adb1a24f00842c4a359b6e15e63ec88d74ff23eb63d8221a5ca558232200bd8155daca6375d1b79424d2b17a5e6e9795d6e04c4e537b15d05ed22a1f3c15444da07a32f217ab47b834ac1261cecd53c1cebf04e7ae4b7eb6d2b879043e9f37518c55fd2effb0c68e4850c13b59d98ae6c99deb06cc0b98bab10af410b923456f69f006aefcde22ae8c7c51a40774b282dba335ff6e64831724fc1d851f8a2e64603fa8b7498f0720c3bd1ed40f4da3c174e3627ec0e49595de4dace69529eb1f93808c5085d488e5bb956bee243bba993346447ad2c43dc94ff4de32da18d527308bfac412bfdde363e419bb1ec5d19430e2ae8af5b215330582b1a6b2c04b84cb6f7fc66fa7147f285308b095c22f3cc3eefe443285a0c0525813fec8579e28b8cf5355eb5b82b68f78814ca17d6eaf5f61cb149a4a851fccf7a272183418fcb5c5cfb76852c79802aeeedb27ce123784131168b819c5147a8d2f759f9f45e78a3d3a3f40a301a22e95c6202ddca44af16fcff3e1646ef952550dfc1977278c221860c32810514888cda3b622b78cedc1e0754f15c2f5f08d1c04979f5a4812f0dc97b53a185feed90960b5e2dc4c0388071230772621e90a2358219631551f3b61201e5e3d4e63ac7c6b4890c82dc6d709478abb1323eda0483edddabc5ca476f63ea749a0dfe6fc9c802dd13b27e1eb04febe7c7360d51fe67866af46c0e8791339e625fc67db344fa5d3ece6df93712a228476f2b889f8fad48d14956217e8d0e8b4bf57d0a9c77f1e8e3295450722c0f9cdfda83ee1a3ad1a0acf698cafd8d7458eed11252dd49dad4740442aad8f21d995a359e17c99428fac6f68079736526208e29085e6944045435c07ae59e0d3472ebd5b54e5212d63caafdfd3565692ab9da67ad838a594c5cc24baa746a49f0ec4f19f98adb3c8af873a48f051b4b534722bf8dedd397102238fe3cb373433ce88e621b3806b17eb9b07243127f650395b97471381c9362675c95df33542f6fc7a237f00e24ead3b006ba05bc30d18f104d88a9a10c49975bd8123c4afdd155ae62a93414c99d0f9d8d8f91b30355d4d53932269f8e11bd4bfe8b5540acc3d13fcc2f3b0b62aa24bd62ab0a2394ee7f3a804355464dc84e1047e70d7a46565d0235ba49f1e2eae7cfa3356b2a24b02a1f7bf91d99d7139ebf0e63c50c212bee17d20a78990e04123753af447872da7e859d2d2ee09c83c11e708c256e6999fcc9aa669c05a541d3d9d945de42f3964b9bc9db818426e991a8bed5ed4d1d34d2887c231d761b124f15997bb3e1086ab93ba1d08199398bb1fc8254d4116cd33e34d520920f305caa8931715d04da61440293895eacc19103f58d80034efa4eb3f412913dd142634e9398702c2b7a6994fae105b39771dcadf41fa33194d357c353e5a9bfffd72c5f06cdaf3bcde28b50e8dcecd0884354c7399f27061224763387e09ca90eab6c42ed44c32e18f1e8b741480943b9486449ba6502b842aa1fdb697126ee2881623bf72c191d26cc4c9424ea6b103303bcbc67350a55aa6d27d8e424305736ea4c3ab4f238c9930fb15950f77a603da073b17608551fac40b603afe68f239094371a6c2879bc3de035e666108d0a2062cd97a2a895654ce7c605862ed647d9ad13d1aec91d7f74d85e715d226ef23ff60bc1603206f7a7f8a8f8a7ac861bb1ca25e2b6439d5e8ec616c66d8e0181e879168704d7622a6afd9db6be20204d6040ad067bb58305e15251db95912b4c5545803c21db0b06a88dd096b40eccc70a1e31969199285b0bc8eb19d0e018081f0c6d7ae0e37751dee15e2f875df36b630b08e1a0533b7e68620bd9971b0ec8bff45bf6d42082184ecbdf7de72ef5d0b530bad0b2d74a5c4e28d378e60650e600a05496001b4eea8e26a3a22d9dec8b5d6abbc1be5fadba894d7bb68d4ca2beefa7a3ddc47451484b228bf2ac490867cc18aebaadbeaf15d64a116a669398b0de5d18269ac5b96c38c876503c6e5f1a4b7bc83e16c68b6f63631eb6061790b674333cb2bcb2d67ff32164c63cfd2833dcb597007730b2ef1e8ccf220172092ed597057e2c1f296b7e00e66165c234f433f4f245b96d7d058afceb2c23580076e013592c9ad7f6dc22ee26c3cd5fa3ed5ade2ce8666faeb59d5915e9e7f5178227730a857c50f90e4be0d990ec666bac3be2646942851b23dc4412ef0700d0dc5d26ab15a4153affdba5e25a4c86b439419eb481821328353672c5c358a7416aefb91594e6a716bef25913a53aea264975f90345d7ec53c63aeaa7a75d8b5cf5f1d76961fb97a673a6094dcd7f61a7ae1202ef93af6e6e6b7575c0dfd1034d849a7c136bad157dfb063df305c73a594b2ec2aa7258ef4975bde8223ed8037b823e1b9fd47de7ec1faadabdf5e7d7235cfd78a7b1b0775d077d5bdea215e73bd23224f1cc425b3bc9bd8c435d7bbca3a76bd3ad6cd6955b88605275162e5d6caca2d6b45746b74fb349fa27223af4ff3f746f276955fc72ed36f46d7d75e1e712a5c0a6744846f3cfdc81aae9fd7b8ec4432a591bf302ea58a7b1d46c95d75ac63c6a33a86bb0b773689f5684d9ba5189050110626391e23b9c8110335dbc4528feab38720305b5c02a2e689314a64a6a0e07a2f317ddcfdc8ef6f469637358a06ded426695f53df1111c425db7794524a29aeb1aff86dc2945c79fa0e0676a67cc187217e6f46f7704d7d0737103f7fd473dd3bb439625c637192f88adfa7f7f75ee654e27a3106ce787131aa7172b93f3256bb5a39ae5fb7bfb0656b9250d8b01b9288c02190c8acc12531ac06b77b424108691494893156da49651079be3307c0fc7027244f8cd1e0762f951f84294bb8f3303b2416177cfc8b0fe25cef057bc195ef00d76bd40b034e9e2d4f6dd7a6014d5de643889c45e41ef3914896b7397690ced5567c2a630fd812a9b0d77075df641a6d442602a10c1883fba8d8c21228f939e1630a1531d20823f7d226885f45d86124c41de97962291f16a38c523eb9de10d6acbf364c5a8734d6e93b17cf948775fa8c8725ed3be3513fa15c62ed109dc8fd1efa145bdcec81c51eda283b6157b212899ef2eb0d617313f803afc8af1ed2d4db8b26e5a237d7a51c8aa4e8198f948b62766cc2549ef308d74d9af92aeba15f9dce57dbdb70e7224fdcc9cbc424da455c92fb374ae6a83d89cf5cec2277af317357ecd9f16c5dd2ac070b8fda145fe1d8736f902dce234ee84091b2e2c789d08482d30412253c748a4675909bad5f1a7decc1d966357d932d7b2ab25092fb35eb11a768938bd8436a53c46470bb98aa1a6331b89d3bdb19663e8664fbd8d3a8f96c5f6518ee1104e66a653eae8f2b4689922bd747642136ec8d7a9d8d1c532f8d8257659d7242d8cb5f364a951a4520b015ae813c3a5ff6d5abaaaaec28eb2139692bae5760ed889127ae8991e7abccb0e6ce746c795e94edb8b3060265f9b2c532ab91b41ccc3d541c6cb138c8cd599dd6214664faabbbd8864cdf2e598ffed582c91d7d93e765bac29394f9e87710b2dc91803c714d02f27cbf095b6a43740e42f37caa51f07dcd9694ecee093306bc8ca1e0cac318631f9680c450a4bbfbfe0310d245caa651cf0860780271b25c42de84018adc41276e9e0f46a05130083fc8300932c6fc37fe727cff8d820d779608093513bd44e3341352480ae589a47184a490753117dc526b9fc0760d17b12402d6b5177171a9b74f40fbf50b1761e152df4f60bb75223313d07e7f71a9b11011b8b7b010fb803773e3a99ea4c979ff6668a9af9dc84cc5957a7b04aa6fef6f58c89216a2dd5ec8f6ea44663a881893bdde6fd77086311dd2852326a24df5b0622e7819c4361892db9984de8ca951fdfa1bf53ccc68147cdde1bd544c038fc09e49c090db7c55555a86f511218a3b9861d90edb59c6378e50a3e45f73d65f702d39eb57e55725061121b5be9790148a7c417fbd9780389ee4eed51730de0b7a7da3f83030c69d7c524abcd57729b1bceffd8ed34bbcb78422a5b45aa665e6a3ebbc5df62d2a4fbb08238c90629aebdb25ad5f50285b1162eb37c6905256fe7a5cdfa46c21f146b1ac40628c0cf718eff9907f6f9c5e824aa19642d27edbaec1e89691e8dd7acb5bd2ea068294c13826bb71671303cb7718969d48f2755dd775d5cdea25200df92e135f70d7a9f6150e7b0a97d9871ba74d12a6c01508e11f5cc15705775784efdbdefcabb5d6cd7aadf395090a04295befe47bcfc234f4f5ef0f777d24cb2336e7bd76d683f53e71c7e1d2fc75791912e9de7a0904a9b299f9baacae7119562f9ff5aee7582417ee6ce66b261ac77272d23cebacb8998034e4df9c73360e131087507e99ecab7ac1048780db7fe2f61f478a2f0a39367069def3018db8c9b81e5b8e18024a6340ec8ea4a5155e62d7feeaccc7c4a37ef31191e37be87a435c2973a4136d9a394fdc2e0209492f44272fbbb0a5f9eee6790861774308d5d00266395c1c663ab68f41688544fa249148b7a457fbd2a8cbc29242c5653909b23cb3642e7eb98e7bca55ba5492e7aa30034e56b98ccbfd6639fe9be5e07e89543898b9cb9d93a132921183cf3d868c5f7114475193f1d7f7d2716f6530545eb82035ce12472e112612a56017a6c2711dcc2f0178d438164ec295d7f3f3d813b7933b797e5efe00e22000a4b123a1e0793abc3c2f731ac57d5e3ad1a83fc63b1b807901301f87a250a3e0e7e393463d229ca1499e27b821c81dc8b38b51f28c6bc8f3af8b6ac8f3dcafb81257a2c6bdb38b520dcc2a0f2273bf66cb8d311c046615dc5d1d2f67799348b6967abc9ce52c2ff18946c9f8c4d75c901ac5f27908a551a5cf169fef228d72f97c00b8e8d3a6f91bb8d8a44df300e0e24f8a95e9e0b85fcdbdfc7a39747910994ba516a552e9f1d585663ee44b3808cc2d70d72fb8d4837be9250ecb74ab601dcc76948248eef1a51a985f1e44e61a289465bc66cb32641cc667e6439ec341604ec15dfb50b90c1c04e617dcf55f5c26de2cc726ca766c98e6de3acd8bdbc0acf26b84714f87fb7739380639fb32b8c81399f4294e117ba2156d9a4ee4edcdc1276d9a87c1c1a136cdab70104a9be65f707dc335896b9c5ea2c4f591162e5ce7340c2ecb499789a408b4699e45c45d16dbf1b2e8dda9ee97ade01fd80b2e147ad2a8799886a7c3e8338fb89a20da47d643beb31ee4fb2a3530a73c08cc292fc0435d9f8781384c90c6fc7c0e4f07013c1ca6c5b0cbc47622cf6b9c50379185a8b98389cf0666f98aaba9519e00e64d10c78b91bbf3f622ba64e12af55ffdcb96551324e624f32f3f24e4851099919fdc06e46be23b8b7f240167aa5748202164489428ae200634ac810d5166e48d109991d8087db4dd8f5cf1103883c48b3283e35293446225e4a7949fcf88c442ac16b86007282841145520997937226f04df787a3732230f815386e082313bbcd38bb9d80c6ef77c7c68d1a8f9d4bc74ce7a7139529670e561da042f6fa4504121058a6488314acc1ba1933e9eace92a616fa4da4a7f4309d28c91798a95b03346ecfbd1618391264e9ed08625334696f4277e6fee51d16d933c15616d9218779ba448be0141186a5409beffa888c2119bbab9910d08c2906c1982d6e16a2176c42c210df81d38bf36c1f7208422e85fddd7d62f460d3e08239186100557fc16e52604f9653e5232c49dd5c028b04647a5434696bf2a7d356a3531cbd70dc9f2e120234bfc1e148dda046f2391089b060f4220950d47301c1c2b9278a215a532672661e4515aa456fb9ea416c8c69e92895853390fc568c485a72fbe2789d8a93e4c48d9236fba230dd177ca93298412890b2f698c71434285222427bf1824e7118b134f6f56d9a7a4d85346292726a59452ca18658c92c618a59452ca3e26d970e1e7ecc08df2bd57e99436eb4155c18eb2626ce4425ad84d604a604ae0082f959f50969131d23eedd3d333c5f56cdc0c28d3775b8ac4ad00789171fa6a9f0cc97867a1543755914c3f05957100bcfe823264fc6539645ca6ab2900326dabaaaa76da4425146daa96149259b89d149aa1afc9b7bfccd1942cace3655c1fc3c5df4b6119550e73f487e3689394e32e468e010377a49cf217b823b9c0a516d805779665856ad96549a05b61f9237d4657b1ac5d69c9ec8b2c69d1e84e75bdabae8aa33b54a7c2d67274c77ee596a33b52ac7cfab4dc08213356dd224beae82ad8657aa5629afaebba7eb9ee4a1ecbb270f60bc30e457557be52dfa8ecd2ca0bcf94c6cd2976240f56f1ec11c31da9e09d36cd545f6fb4b292599935aad6b22c06865b3ffac94a9f36d1af70b289fca1d95a8b3be933aad9679623c3f0ca7c65c7e44f87e15a8bb13665192ed5bfdc05913b7b9b4c36b1f289ccd247fee01daa2385ac775467f424c949cb5e05f016295474f52b9885a34ab2fbc84ec382a912e94375e0885e009c1cc282bce2e1903b9006bd68009f71daa451389c9efe34ea86d3d32b9e0e700ec5137d2b4f4b81a1e2f21ae576d327dfcf9c78a2b7f6debc6daf6db8d9ed5b7ecd9c18337362cc9b99b981ebb21b8e03277744a7330680bbce38daa44df43770f4a74d513b0bee48dcca3c1ec5c09d85f1c205ee48b83bc59d2973d861b683ab4e97697ac5c3814aa03b91e45ce15af85d9abe512b3a5a858eb2a174c32bce74ec869bde5178aa4a4dc15c3d8976da003a5bb8b38936d1674ada14869bc275b40a997e326954379bc874ea38d12895d34f9e4695ee5f66b99d4a481726b1d78a81e1dad7a71fbb5e86cd21ceb2aae56c64ce80a4293dc605f0abc4c5f88d7139c3c2bdbcd90a2b71300ee3a5beacaaaa2a9a6ab32c0cebae67d656d9e7007158bf329677db6bc5190bb6e95c370cb10b7bd565d8a62d16dcc1bc625936f2bdb78795efb36c47cb550e93830dd1abb893448460163b4c3d86ff5259e564ce0e0371d867b873f10ac35c6e2fd339401cd9abcea505eeba728133ac47758b3b582bcbc3befab0afd561200e1b9d8ddce29d8d6c69d98eed15671b9703a461b5c02d685a5cd6aa6439ac0bc3300cc32a5c8f713090c67517eb32b165bbb6dbb7d4cb3efbcb7a64380748a37ec3d9ad5fcf01e2a8bf3a799d856bc1dbadcc0796b1e700716096f55196c3b259c6bd6cadb5364be1eefdbb39401c30df9be5b8185e1b978ddc5dd2b22ccbaabfb66327926d3a6f380748e352f9c5692f3ee25e9c761a75ba6cd48b5798eab489ee6071ab12bad3262abac5272e0607e31817e32f7b816509972e13633c857bf765185c17e35449a3aa4ea32a1a6dc4548900b837f3b21898ea70e16271eb6ca25155e7e950650a0565327dda94e13944b5673aaef6ba698f590eed57c4aa8eea649f48b457ef64ae7037737a3a3184ab7dbbf64b663db4d75fd52deeb27e590c561c66e1ae3e08d46e719a56939c3e9dc89950fa447326923a87a80ea55427d25aeb5cc2edec4bd65fa6efee4b16a63a544914b7c2f4a6e23964c49d4eb4893ec36a768bcbaa0a03baf519c64d286da2b7c892942cc3e80d567d7b0704c661595cecf5f52a97e98abb54b824a7576e42e998d3e9e7d089a34afa348722bd69d4cbf42a19a63a1816ae852792143c73e411f7ba9c0d660f04c675449ec8f5409d55922b119e05fca0c00f36d6be6edb7dbc26b9bea6660c60f7018165cca751177e13ca95e454b31c96a34ada44ed4e1b80de1e71eb2f98f2975d486ca75f103b714596dcea3632578bb3af929c7e55556765755597e959ddcf6cc7a5a9afea2fcefe9a96750bdbc8f7d36b75c2a5ea6f862ae9137d2d5597b9c254c7889b82e90d9e436da2f6e6be3974c4edfa87ea501daa84ee5c310977e3fa099d36058083bf816392610a00dc6bd30bbc0c9f266d6aa263e40e7cd231d2a797c8ddcdf85d37d14e74308b0e3e814275a4904dc74c1f7845132be014108a0e2a814ec026e012dd8d9939363a660e8d3aa67fe2899efe362a3b7d4dacd8c1c60c17ddad37d3db45fa1465d026323cc61c863f8550323c0c7aaa1363e013ef04af2443085fa23a53d01e2ba84f13fa93afa040995e0ac51858e49de097c8b6890b9dc8907efac4180bcc1c7828f0221f2b369c1373329d4331e6a54f3f31465a70d43ffd9301c98810f0c2b3ddd3bf5ac629ac96b1536de28142896cc385ef64247573386e75d256bcd3bb941594a9fb701727ec486197e0d201a9f5cae27854afb0b2ae571ef71dd481e1ed95863b9bb8713127b97edb54ff3ac6f6a9be56fa99bd7bd4721d11d97636dbead8e33bcb91ed63d6c3869364a77f1563d826e65fd6566b511ef0b476b2c21faa395df05e8c369e62a9476e336c57f7eb483bf667774f49b9773df9cc47ec186347283c29adbd97443a0c8cf471d1af0d110805401149ebc4f89ae448a78c398deaac1359e4eedd239970bb78241e21451d2c22c949c1177c8e7c5218a17d304b2933176d7a52c6486a53122ebce949818a0e40e1832c7e50c4c51e6216d7491e97a5c376b62cf6ebfeb23d19debac559f11547637d68bfb06dd3f5783999f9d07085659b2e78f9b8c75d96a3ba3e2ec6dd10edd232fc6ed3b0b230ac03dec28ae3016f310ee64b265633db73f0dda6b31022b0fc72d8e054816c02cf7bf0124a2804cc1de3e96db24c0f8fedc434251ef073e29a8a835c8048a67888799b99271e623e88284f3c04bc4d167185fd05293f9b3094e1654e8677024e86b2bbd29af9909252794a29ee496b8c3ee063673ee0272704cc12dbc01c1b7744e08950187b70f50e0dd339a0e9c2d71eb822f074a81982c833cd983c748ca94ff02f303b34eafadbb84ee6ed3f74dbb7cbb2b2ec17275fc6c1bc71d2caac5f70dbb04defc8b2ec3267b8c423fbf62dbb382c6ed66672cbb84ee6ec3f344aebec9724c32df1b86eddba34ed1b37ba5193da963bc3369db577b6437b4dd4b4cbace1120fedd9336d9b2412f6d22698a18b36c19aee1ccf434d8eec3a60d60e65da547140da0433ce469b60a094b2fe6894962d809319c325e2d62bee6ca553c6be758dcbbe713eb46b3a0c4124bf87437db5ae7134f52f5fd7c334ee870d77daaf5f170744e896786cbf7e6d3641005920e35eda7429dcee0961398818f3a37d9e051a55735f974f87972fedd24eb31df5dab52a2e919c7133da8449e1f61b1e5adced78b9a6e6eb4162beb00d17449b66987e2e116deadb04d1a68ec2a51203c285cf91b3f17080b7620a1632c2f90971d7376515072aff7a685c8ad74188f9da83c52fab99d8a6a6e6794827eefa3535bf5c8a97b871709578c4bfd35ac5e54a3c22a6b17faf55dcf8ea15ee61b1bdc54172ade256ece79ada04ff2e0a37e28650b8e435e7ed8bb13e71ad3015ca5675ce171b4f6badb738d68adf84efd20a08619c73d6396784af33c65823a4908746fdf021c6cc1b327f26911e96b9416a28a4833c8f20840229dc085d4ad3d5cb0fc9d5ac73ce6b225ba9050f2bdc4951754d1369d535117cc655224c5465971087e8198e15acb4ec328d55bfae8b32ed9d066b8aa6a564b8bbde65d730b6996d1f7fc1cae2aed2195b042b1210460821b5f6d2525b6d07d55a35ec95bd34edba2e6b6d66adbdae65d5aaacaaba24aca91426689205909f1526d031414e8622c8cf8a1214c9d7165f6a91a6695a1571341dbdfd10aa69f52251f5aa8db8caea649ed56ba69046c43e8217c18b46227891768ca3d9fe4617629710c7e898866b220df66d749916bdb318d4e84aca8a08fb36c2f222dc5988c3a2908686a5cd7a5cd9c21d7da96f3185342a9629b04ad1c493269c34c1a409253987fcac20c1508c1dbd4de7a83566e321d5e03b28d6441d44b2d5880819f26c72ed273415ab5abd96454dccf0b2d3fefeb4a04c9f43c3346ed426fbeb573677d054dc41ac7657841f4f8d37dcdbebafe856ed29dc7ba75a5dc45d6ee366c6704784524aa29046c472082462a58de2057d044e0bf12ab2e49dfec29c8cd85a34dcf8ea7aefba7067dd8ab2c29d0db532b1ce1a1a8ae34b0c1aa574c34b34dc08284d002ba2540f6784c019edd8dfcc3b0ea5373e40439e1f7ad6e3e9bd72a4369128a52930e439e7841804970ed15a243f203a149364976911508cc96ee2e99d74a70808e29b1843d3f04eefcf88fc3e95c8ef5504f99ddec498971dc9ef2fbe4c0a014916996293095e9ac6591ce5ea6973364b7941acda0c6745faf46c66f34db6447603778090ada1fcb09fbef90b269e4c6d7adf89e276a68a736122bc2053dcd523f9d1a187271eba01755eb63dca8ab4e9cd596ff2bb801865186724a64337b89d0848d24089238690eb45402227af5cec4f0e88519c7959c4194e9b5e762384db653774e8e1f09edde4f78e0e1d813b59c85d9693dd44986a43be71b919b242a487d0ea0029ee4e14657821916e6a03c447296e47243fab1bc2c4b6d1b216d37494c90b903c340f0bd01a77f495d5321688516e6c2b18b904f51ee9ab75fd16bef092ee0b6853ac300f322fcb441e602a901467c8147737727cc4f14e6c3589f134460c1b15a7c472ced930be8804769493565b59179669db15a5a88c56585a482e2d4a2e5ec088710ecb7801006ca2516d8279371cbe7ca585a506f7f24e3764d365fa0600bcc8c0dc63c078e1a2d4c285d4c2b232524911dd4dcbb0cbaa6ca5535a4b8449ca2b379ae285ebe5f7600382f0687426351bae47e9a57df4f23dc6d4a558629410fdecc32104cc3d5e942819f6488095502a39928344678727f50314243474838324e806e748ce0e4faac7e707e806e7480e121d182153d08148cfc70473134e2a1ef949d91f24298b24286583765276e70da5ec1b4ad994b5f0591651445144514451e200a0f405314cde640b6f2db416a75071e5cd7d7559ebbab87b8ba3d9dedb6fbfec7d95f1f02037ede6e45d59085537485a0f078b5f9b3a6f4eb48005cbbdeae2242ad8dee237538762cc9146654dc81cbbfdde9a6176f3a8493aa3c499591287b215fa89a77e503cf583725ec45dc65d397e01477658834628d15b52bec292c2b17cc4d1dcb2f2abb2b0b0e011375b444d6a508c098a3568c4c9cc12af88402b293f31afb4b4b4287342864c18b1ace0242af8875bc1efe130e25eb6720c8a423146e510d7aeb2bd19fdaebc5f599ef27e5dc3d321c8cd198eecf288e81a712b177134a7ac3c3bcbefcaaf6ae5d60acb8a8b298fc0cbbc527f47242e8eb8f77048e98743c6a9d0b82656b9174f778493a8e0fb7b6d156dae433731a65f5935cbc9f272b28936f5ab43314e2cca95472696c9fc2ccbb169daa6596b2da665963bd2c158d6e26cae92d4cb0ccb2373be58723d1b77c7cbf13b5e86cf62512e101faeeea494fd7c68131008a451b061c386f5407c6813057c0002a50f4024fe816fcc1f1f82e27fb0f06591fb0fb77c8459e41b2ac290f35cb4a9bb3f7deebbc4a59b476d2299224ceec9d076e0ca72c83f0e63c38d3dbc27c1f98c2cf5616e3c77ee211226457267ba1d1b56019b9ff5d64a58619218db36c402e627ff4cf05248963025649a7163075a29b536ce0ace6ac2292b2c63f28102f0369e12c73ec43cb429fea05c031ac79f1c7f346cf9e303051a05444a4992403f6ac8f28607b992e0c26c2b92cb84314a39e19c104bc195b983c931478ca336cd49a9a9c25aa5f61e0e108fda242fb114c8cfc3571e5cf90e264b28670a1a4b0ccbb9f24064c679d2a797279771e23b887892f3f224d2bdd77e8796565a6965a5b83365ec0412669946f21331345c197c6306aae38d39e76f406e8709dcd8a151f0489cf002920e0841c2a03b5a9fa7dc55b99a2188647a5f712f574e08fa7a6f39d12f58435fdfc3817236a26a331dd82f87dd9ebeaeb6d6082176c718658c360da18441b8e29fa5b3f6f0d080782262622a024142507284fdb2cc026a0328ad3cb429461e76f861fde0a1a701d68d1daa1b96b5c30d7be3c60e3c34e007a53b60b6b9b083a931a94d170bf7d626c468c346b461233f27366c1c5159f04148036f4158d94ab510638c7df9883536840b1e928ef40c291fa9512fe5639a01bb70bd27f41c420189858290bd24dbd9471b85d4738f724be9e482500a32f4bcc025a4284310f6e2e3f382bd4882eb9d0950409c6ec29094a45b199d90cafd196dc2b090390d310e01b7534d7e72c79926752f21772e725baad51ad45a6bec3e84b452ced4a64823c4d1be1b420ec6042d6e873e457cc389e96d8a8d8ad4a6d4030791f112a34a1a0913200bd6f0524790548a2d0c49b1852fe44829b0c09152cec92305163a99546bb5560a2c9c482c7aa4c0e289145c40024ac1851368af4df605d79fccaf5155d2fc1a65cd57f8656be63cd1a64b3ad126a87365a8e4e1705da62f539baecb2bdcf87e590ff9082beb1857b30feb104f4cb64a0ab7c4b6b591996234d89dafd86b9603c34954305ca3c43e3118392983c02c3fe931aa52c22e33a6c29530fc37f3d2a7eb1817e2b188990ecb43ce785def2813db82c6c51dda04b51e22be71658fd884ef2acc18d7d94ce3a3e44ad87c9bae67dc0b775d46211f50c40b6813fcc5c5fc3a26e5c28a2c9930f3314b7f4272dc365dd7f375a097469578cc1c3f73c42eda74fdba1e1006e47a2482933797874675d6038bd7655adb5e1289ee755dd72594afebba2ea8245f5074b7201ad5bd9f7cfdbacd6581365d40da7461f1ba0f8dc27e9d028d8af8479b2e1e7670fbe260beb00bc344b4e97abce25e3cdecb8569e0d6732aa5fdcdb28eacb5d57e623ab18c51b05b684137ffe89cf4c5860f8312a3adaafa83e6e91f349366923b8b66d24c6080cdedfa7be95ed54c1e10c4167730eb61e569653b585ef330b1a62dfb755508e12b47231f85b0d654ee5adcc2ea720b6f2b1fe2a95d5c0e2f5fbd73b1448458d69bc7ea1ecbd1b84838a3ad892e9fd66367d3efeaab0adbaa82c914dbb4cbab8abb66525515ee80e801ef5259ecf2d9c1647b1f62cca5b5b22db08bc525694ab955f5aab26f1e88a3bac55555b58099e559b6c3bec234d55d8e4d4ba4324bd35ed98e791a8b5bccfb40b12de10e66b6a859e40b4a082184d205573c90466461a9f08b312bef2dc3a618b3825b05a76017c3ec1d102488ed1beb1f401cb1febaf0656fbd03828469ecab5b31f6505d425a75367dddfa49558f6fb1dda2950f9456df7e6476d949f3555dd5655fdd46c760afbe43a366cc9ba9de3f80389a497ed9310efbe4669591515423288061e10239e2d2548f1d910b5adf0127d7c91f72f543eeaad7cbf40f190852a6b87f0069c4988734913a0412b1a6cb1a6c3cdabf7d0cd8dd19edbeacaa290f5fd37736eed4c1c58447a74d10765815f7fdc5e667b39517b93f2f28638cb16504c04c271f00b21192e02411676096040c8ce049b18089192b53a1822759c29c467518129d46512a54d093e30c854f64aa84dc8d72c7981faca5f9072d5c9e9d1f254f346192e7610e74e22237096ed73d334b59c2ed22a5ccc3d301a280c78b812980277a8a03201a644ae10b327df79800731e0e14168941b8110311abe35410e73aa555154fd7ab5f1707713878433f01fbb63710278836d1733fb4895e02f4f06608a7515d3fc945e8d01299f6d0eb27fde4544889dc91728ca25be4a6729ec8f3915bc9503aa68bbcd3fc125934f1a49d8002afe8180b1c32893c8db287f2e449162f0b27195a01a7c8545aee713b5e969163c9a2ce3abf0c776f8a3c9f0483393646ab3a9685cb438c8133a5eb4432fd4b63cfbe838d19308b36d113fd166e7d4c82c5499d1c292d8e346e26e88a12a286884c63133310b3c4dd84b76d823964f783107d63bb1feae963cc725c3f08d13759e21ac9559a1fea3bcb81037d5bda026aadb5316279186cd701b3c8fae4ac534e84ab2b7a4d7df51a0dd00fc9d585a8d86672b592590e5b61c7b28b6a0e6bd3ec83448caba9d9c29df520315bbfa8bd280e1273dfeaa1bb2137990eb9c996f4c215427ee1d657975fb876c6575cdfd69a1a6f32c54432289fb836cb4de0c25ce5ec39e7ac6ae475410be411d77ba9c941af0366dbd824b978a3b4bf5fd67ca6ab3acc1ad50f87ebe240ae4cd7a31412a5cc6083c1860d1b5815aefc91d40c5e116edc7899703a0982be7e1e03f534f23df1bbd5499b226c206a5c824f6715c325da14310c8a4357e25247b9871102c9a6820d1b2dab7c8c32b2e60069c8cf37ed08136394092f8503a099c201509e2af3cd6b27858332cc9f3c63e7e8518f504883b2f7e4fbd9c94f6437f9fd450ac9e52fcbe17299ce4c70b35f6ff196afc85cfa833c5ac7cd3927f7548fcf0f129d1d1e7803142434546bad260bc3436bad11e39818833c40f1c5a865f317cb2b1fd555b8ce2a224a8e43f44114e89d2084300531884188e49de0b17782c7c9b29c0c08ecbf7782dfe0b6dd20c1dcf762fe4ef017dee2ec2fd7511caad3d11e1a941f4e15610efabecce890366266c9e462aa0477be8b293befc2c5297874cc3622431e9e1839888580b99b3db64876e15ece6076c101793800cd9eac8928d4a81a83ba0a73a013402c0f84cc29268ea99e986ad49c02468e0878038f64a8140f734cd2b8147b22500c6a03bc7e4682db452027908ba9d8d306a8de2475454fcee267f66068c846704b3daac3c347ba7dd22d4285ce10949beb9919d601c9d81b7a410fe8a55ecff3793f11c21a2019fb03cada65bafe6534c8cc1aee80640ca3dca3992f619fefb0e824065d08479ce4b61814819c34f6f99e487a78d37066cd40a121882146d0768cdb5a8e6cdc1aab907e6ecf1467d6350efbc575f096cdcc49703e13a3ba6fc6b29a08479e123cc0a2938ee9bf79c108148378e6ce853d8ac84c224cb501de63863caf7a046a949346558fe2c618778450058db760e02545e4cdec29e13967758bc89b9e7ac5fd232dc2eda0ce8410eedc47dcd922395e05432410fa40104502e88894077a46e0235360c4953089001e053c281299766d046c39e452feb28981362253dc151125efb8b823bd256585ab89dfd139e20b5e9b99610a89c3401b91492d5efc7ac1bd9996ace58a6ffae43783f29b50666cf169693122c3bf2e005d117bd1720bb469c70820da881cdfb2c3419d233a4a8cc8ddec89a98a857cbf3d661148e8760f0848c480dc08045be8ab598e963622538c8136224f6c01cc02b140a338e844964313fd6814ea10890f54903b4844bd4596d4222d44237729d831ecdd4a86a41bbcd3cb70a807efa480a1281e8d975b329088e79c13cf1ed39b3e3eb30767604ef82a44f6527cf62ec336334728b3800b6630464c6bc9d1729946c28b813cefb4842b0526e477088417d37f44c8af8afca013f26b1cb368d95d7c929f851c8c10c20821e56a88c82d2dda275753738b100932e9168129301c915360069f756e69895c929b21dc0e106e66e087cc2cc1407c89c73cfcc440c49af580c7002ef58079e530af7ce2aee54310c918b0f2ca653a624e9e4cd71ddc6e36d18cb8f4f01a863c6d823c31f6c429daf42850c58d1c102f19c214a42f49ffcab4185f621781322e02a4b7e0075d64388a2122c2edda8cdc72975f2edc8f0ac56d79f77c227099deb8247d8d4b4204c56f88be085b0435ecd34949c33a3a6bb3a751f006094d28eff447c320f7e6a1923ebd8deb80e4ed7047b334b80375b077504709f64851499b5edea0cece08c3a51e37c8ccdb2f17040ade7e41987d1302cbb2ed6230fb76b30dd30e330dcb36c8e302973044c2f226cc69d3a341d8340ae21fda0464e7c607737c8e3f1ae5f2f7083c2cbb8cb28b0b1797cb8e813ccf7632e48931d38a3ebde36ef674b3a7455e40269e3d3ab8f0ddec21715d843866f124c62ca250de2eee9eb35ff149a3b24d16f109182ebc25149fc89b46915cdc51c7cc9eed1177d82f23dced50daf4bee9b8db79c06f9f3d31065a1b3f391a884bf414f7a840bc6c9fdcb6bd3884839ee983c5149c3e6d80077966cf0d9c346af64c2baa78a79731dcd9981c1f20c23bbdac55317529cbb79e8ee5d7bb2d4017bbc85d047ab5c1b57087e5eb2505366422a44d2fe27737adba2207535c056efc8e1eed1526a24daf9b40f3a79b3e44f2cbe0cbb21c99868178c910bee489858cb2dba6f7865afe2ea4ffa6152d5c091e96621477facc9e363d25f715e10344807f2ff5585830bc2a2a2b1c0f26b8ddec793ad0a743e7379b74cf0792e7a194173be4b24fae72250bcb72c0aba2035351c13673077688319c8199a423e4a1b93e492e484cda70610a3b69d3a3290a538da2f851da337be2e9d114e4793c346234421e988a4112b8dd1beaec7b4a8497746f88884695b087a40899f6c0bfb4e93f14771328bfd91331bd2690365ff697fde28e947dc3ddd5304f8c79dd0d79ba421e8c0d375ef7b90eb96b36c9ef95e3b199b97189499fde057920cffc819309b77b29d38c3699be73bbd933a70f4f1a72ec993dd38a2bf2fb2cd231cf07c9fb6cd2a84784a126f97d3ac9eff01088084359e46e0ae5772149094d2177134a7e74429e46753b402632efd0a8124c9e3df327e26ece9ed718cf9eec060aa982cfebe1be211891ca4f0df90de1668a9c8ac07bc4424a6fc6c6133c4c770372379e20299ee0923a83fb66525ab89e01ee1bc2113e19d5f513d94d56a4518f0b433822f5ea12f9dde526bf5f47a07d8f57ea652198735a9cdd489c861723028aa7a1a7833da98a4009232e028a31d6de4ba2d7e9508cc98c6c398220bfcf263698af548c9924d29512c3bd0ecf4c553f575022bf2b209155f2ab428a27f9e567050874aafca4b0821a722702eab29b7893b26e200f6e97dde8643ed94f7693e2c93bf9929ebbec468898dd644cdc6ee433f2b1d6aa32cc30c30c21cc9d0848450749eeae75932d21435466b66f580ad04f0af6e3a33dc5e7ea817f3346b46ff84ac5d3c34568f8ea89a7f70eb39b9d4be54518b1ac632f4e3ab2e1228c6c9be5f294a7bc252bc248967d6bf1eddbe82c4518c18e847623d8081791b978f6acf495228ca81c09ed42700a3053c24560a563c75ee02254b0916bd73eba50d00c2002bcf839dd0549a8054b0ec669dcc69176463ea49d15a19d15219f9ef878232a2923da91b0701148c02833462edcb935305fa987c33bc40109a7cb6e7e72d7c2c392b393bb1521d24e8c69013a91760840da690122ede4772d40412d40a923194e3cbd5fdb7284d43d43286ea7b20367deccdf0c028c7c588258725684588258529a85939d243a124fef484b8d9ced2c34340d17a17d0517617df49ef519da09f0f7e24900df0ef32bc5928361d1560377ef07067756c30f8800b8bb38e0ee05cdb85203c0dd13cadd4db1e4c4980b2300dcd91b29114b4e7e5f118a31d7562b42a9bb2274a5ded027ee9e4f5f2988bb37d45d298c274bf558d6359f959f1620d25db618fff6f72b28c608d15eb61dc349c09916c75218f612d6e322e51de69392f2172a30de613fa5d2b177efc7858b67ef1ed00b9c049c79f194772f08064e02cec0b8cabb27b4f2d13b9896b3bcbbe1f263924e0c4cba522424248ed4c29172e28994221d21f1c41369289e4842f1440a8aa71e12503ca538d20f47c2e1483bf1d43d9fe773537d959d9f13ee4c1968a7850727bfb70059d9df5b822cec429ba9654813597f27dd58d65f3c55cfb2bf0cabf808b1b04a4f3cbd6b5825154fefd6ef865578b4074008865576e2e99d27c66c58e5c7843b9800e0ce5a372eee6e85bb9722752a3b7fcf74628c90212a3338059869b990ec297fcf70628c10eb2a7fcf8ec41821da477fcf72628c10ec2c7fcf90c41821db57ce069f9922529ec1a8dcba31ba467af75238059821b11c7b4b14a1992256bebd7b3d3ab82fa583d38d7cde100b370a8aa7f7156e24144fef236e04144fef2adce8871bf9c4d37bc68d86e2e91d4b6d5ae613635690c4d3bb905050101050f77e5a8e8c7cf27b0b929d961c9d96233288c113afc6fb6b03c41d40a1031ef4c007496640831a28f901109804410851d860c90d709003d8f37007b76309caef9dca4e7e6719a2d85546d94a0bcb351c6ca6481237664877695172f162bbf57716a1a8c188f114ee37fcbde56606076e167e91244833325e24893b03801749c2cebc1cfb3b4b508c4122468912a54812303337e09b8469e61a7935de8b24f1995be4d578bf376d80f7770070b704afc6fb0b779b7835de31ee92e0d57897c15d13bc1aef98bb277835de37eea2e0d578e7b8db8157e3fddc55e2d5788fc15d0fbc1aef30b8fb8157e35de3ee12afc6fb0beea6e0d57877c15d15bc1aef25ee3af16abcb7e0ee0a5e8d7717eeb2e0d5782771b705afc67b0b77997835de59b80b8257e37d85bb217835de47dc15c1abf1aec2dd11bc1aaf46554354e31e8ae1be54cd4f0a2b94e18a70672fee6e853b52c4dd1b77a6796fe0adf2a3220a457c7237757e5b908d200c37bf2a86d081dc4d9d08c170657e55482124847b0bb3902b9cfc72f2bb91b975e81013b79b3a53275a0b844927e312fc9ba9a750279ede6106adcb340dac6f8c3bf820105a399e61146da0b0e2d7a6b73daa9fa8440d7595494f3245330000004010001314002030140c888462c160389ec981b07d14000c9ba05674509b874110630a19630c101000000180110012240000be33f469c66da900e3fac47aac3cfbc829cd24ccf63251a4300c543e7aec8535b5b1cadf2488b1bafc70505d44f7b160a30aa6fee2990bfa21bfebb584b0c47a75cd40d8370e57ff379c55c729655cd557179c49744ce9d5529299b88bc853448cb82d7072190344cd7a80990aa22adcda1826d685290b37d61f23f94bdf931cb343483d1de5c1f51615bda974052c2d214a7fef4de30e2b42c1156d7af37af08f66bad12fc459b27e6cfd627efd99769a5c578dd920768c2f9279f8cf5c832b598e654fd8c4c39a2c09658f3664c12ad0871a26c8cc47e382e149504049ce600f35983199fc90c553636c33941a34f66c009507270ce9ebce0990adf8aa3b024c30645be145a8fa017b4bb019d84b279ea6bc4ce9f4d1644dfa1415c4ff65ae48ae050dbb8f5170b8b92ed3a67eb7b07119cfff5e2975c803874f1f0823a14c4d27081377c6c31ce9164230ace45d8e4ed12075791c58b931625a92a4f407d8377a6d2fa1f864d29d22be9c03ca490e1f2c61d7f3cdde971388a0ce81c80c94a8d3a47a3fe9bd77688526d2578a01f4f8ea384657212670b61bdc2e5a1ddf6c9f5cd14e013a92e822895f27cdea52c5dd1b2ae7d9ad330a8431742409d4c8a69daab0870573d7cf5f9d63a5eba56ebc5189473d4e5399cc1f66f5dcf82934a55fe167e6966cdcf67db1c70b30c9a810ce998a2784405995720005acd2e4f1ba084c8ff3aedaefd0e154224b45885f1bbe7431f32135e9c22f2350062c53104febb32fca75f5702da497ffc8514d05e586cc641eaad786c18c606fe7164674e32cf755a0b05cd4d2844a41029e954d24191fe480980e6165937e6b47024c6bbe148963cc1869bf1f007a1ad4a767dda84dc840ff99366715f21f5450f53f6ade704d5b5333da8d4dd0a5131f3af801db1738c44282d9551b962f4d1c829adc0d06c1b0f956f1c792ff509bfa8240ab86ba1efd3ddf5b197913e3319be6389e616b26dfe469c04e939ff467394d98f5635c7d27c263d704be585e1381339c0d349337c3c98b7f9b2614e1baaf0d2ca223fcf65dd6fc8915461f46d605e2bb2656d6683f1eced123076c7ed8261a326a0b4c09c5eacfe8f05931c2528ff9fe929c8bcecce99423ea4aa1a0e95da4fec7c7b92efd4eebf71c4128dbc3d1c90df23f9b4714fdc03af167ac8f6eff2f1ca7f02efdbc0977e5a590de9951dd8a6556bb25caf7ae18a1c518679373b342f32fc099c509054737b1686dcd647949a0e6f7a412d37a9197a96466fff0e9b61f673e584eebc90c6eb02ac5613f91882511d381a8d10f5c5072538ff66c775d717056bc4b43cba3aa198ea569c8026b37a1852ca69c5c80f4449a05a14cf6432685ac07f7f8c768c1d9e05232aafe885c1092ba3c8fda0c56580c413eed2b3c449267df4e5123c91ee89b9dfa233952848cfe3cc06c7bbfb25b8ab703e8ea004cf549ee548507d3c31406bf610cc30cf62ecdcbf68fd324af866531ad683b56e20c5289861ce2c81438b485ee1a40e2bb329b3752bb658100824f8994c77d1b258830876d18159a8b84fa4137932b9c7a482593089849c3ccc164c3534cf06fd5bbd6e073291a2868c66c2fe53b8a73ac4e6e455d16a586485bf66ed94e2f91a2f243d5b4cf570cdb29894a7f493e74f2fbd39d84fd21ab2a1948e9622afb185a6b0ae0d68c786279808ecaa8048a36f86f0b723793732a819dd4aaa5a526b24caf6fe400521a9d94a259f64f02ca6e1a50b89b9221150a1bba6cf4fe6fa01481d91728a051ebce5092be9b08716c488bb97985b9a3d7c7f89d1c2d6018c991e15ef6b74e865dbac784d96e8fde37209a4272c923fe904f4beaade7b58c7e5aa138ff3f4f437904572a3a625d68152d57431f490a26e1d7689660a9844e9ef861a5757a7a501bdb82331b100259339f72945b64a2bcc01f4b2f24637cdf257d648abb2230d2046a0c549ca88c80cd585667df948c09a1a31b9d1e48158fd8681fece9447755d626dda2b7b718749be04235c5bbcf5c4e8ac35256888bcd55d56c888bb1486758eb10919fdcb7379a2e1547be7698c339a5b5c661ec150eb0b5b5f2dda2374df294a6416fd4d3a11a9f621c95ccee9f5f4abaf497c86493ebeced9cd718908951ee11dc8e993d30992498e5cb3dac4f6e47e0295a65b52d232197b0b4064b86c5c5951a2d3d9434edd7c4503f201882faa8c7c8ff261908050c47b69f34821a577728e90f72732391a1b439590c27263e389ae0617bc877e0ca2a2ea94e33e75d0c4025631f60ca492519a82efc2256c639365a3b2dddef116da47c2d5e1a32ba530a8fe886617e6b9eb689e312520ed9a495fd0f4c6559ef54b7eda73c7c5eaf29e69367595a1d0b9bf0476e0e66c4be55d89b4e27ad8571455fc0d9fb9b87f674e413102d2451b50103592fb719a9405f6eb355626120e2905f290ff7015356c64517fa3eb91c29173b540adae97bb2aea13f8dc5cc24b0bdc26a80e5e684309059d4443f247b3f6cabe0c5383c2bdd18b05943612b3b6c0a973cb052fd59d77a2b73db913d7a7d9e23d4d9de0b2e799df0709a7caa53e3dea44ba75ad08840937dbec85c26b40b94beaba445f059642c3e140fbfb3145062d3ae745bcd794ed55b0a241611c83168e1b9c2d6aeee96e01f54af83a7b5d849c440ce5b1fda953ecc1827439b840a549857ab6fca66db3e8a2f43161e612afa8c981d163bab608d5589a6da3cae4f873f24ca3409fc02ecdf9cda607d0e1a2c714a6dba04d01297ec7729785b1cdeb43a68842cb2fc2f73414cbbf6438e6066e0cefc2df04497dbff03397125b0e18d9abba5782c48f340c717ebe4468d9243005ad657984449602acdf98ed6371ae4fcdea94e1e0438c51a6b7effb6828dafee85109c96633b5c6735dcc890a202c019cd8ae85aa6d4cf9b709d86628cf7363c19a68811755d791d209be456d896880be022c1ef393426b7ad9cebd287c497d74a92fec2dbe736715f690687c9455ac3fdd0e6c34ca4583927cb37707887744be94a519db6cd88d9472d6ce17edc9b6554434a611aba7907a6fd2d0343d215100280bd0abebf0217caaf919df62adc7561c2a4b00a2f7e81453ca3798ed0af00e7340c1f8c6f9e6ac1c5292a20bc8356ae486ad1b97669a233e646a29a25e94a63177c5847e124bc97d4b184ccd35109417a29ea497c700625838c2c6b01826e6b84b1da1500b41fa6de9db657a15d95726120d59d3907d8254fcd029048edc95e71b1c8930a40826bfcfbeb7d5130bf62d4131f47bafe19b0a5600b9607bc0d4e37e4ed7461a44c9668bfb94f5b6bad1fbf7e8880faf3bf05025bf14f73978b1a473911ddbd231eef10a6db33a619fcdff7ba4147ae66cb1a7ac1d1168bb5256511777ec5946c7f5f9a04ba61ee3918362f82af097e55dd82a9e7dadd3123bf0a33270ad18a8d9ed357dcec260eeabd199f69613ead3594e88e977fcc84c3c6fffffb2383c561c6a92c51de6b28b08a3a436289548e28588bc32150c9ef2721e6f4e081ec984825274c0a98e492b799d9e92e20d61781796a78f595258ab3a634a6c93410ccb672ecda7f9b36845a2cc2406be8ae397e7ade051e2f2657f4aa8cb2046849342cfb08d9d80ccb73f8f1059959f07d8082a5b193a8600e5708b4f009548fee50d71d01f032b8e0d9f9c4875fd0ef39ccaf0c51f2fcc25af455d04c26a19c8c222e7efd7080e518f7823b744550d00dd208759aef08d560239048511aadbc61467daea229b60f4d21c4d912932ca5c5a9dcdd14021cf3799599c191a5e703974003e62559596c7066bb4f05c404452a113ed35ea9fc41fd9e18b4e5b186d29c76ff3d67e288d307a2913ed75b75b8420f7126649897d6e57d2b4f63660ac7d501906bd35e8b4e61b541a9aa3e4e37ee8c2493f5d73a215052577fe5743c69f5c11de2f4a483d3ea22c1dba143d3a8f7ff8c898328c57049369547b26d8da8f4110e0b92610cdcae0de02df11d9a348f00f42c8f269e64a39ebe9212ee8b26887b96b5869bb230ac7af00fe5a153cf7929506bdb04720b58c0419cb95aa5299b524bf94599d9332750c08b044bcc59cfd67a0d889561eb020ed7b2cfa538f3e58305f77116e207f0cf980dea1706b4b74ae7ae057ec36962e0b71b222f17e9b199a23b07b72e5e3aad165fb238a5f610e9091902c56d65dafb9eb9939ccd1ef606f320db5e6dcf50cdb3a5f2d8323ca20095d8c4a24c95293ad0092c217b2673e3fe1d3d359a662779a48f5f1d2a8b877b20d4a373c5e249d88d9750fb97e25e103c9a3ffc2895e8be0fa363468395d95f716479691ff6b415959d14dfb62cf33d6318d14c6bc7b3404113aafba3e35d9ea71f243338c2cbf6a1e7ffd7bbdb97cbe72d3990764c63f8cef247e96cb94ae010de755a9b4c7a16d0c433edf50a10c0351ccdb0978bc0325030bc79b3bc5f6940882f14fe5c670b9b47327e561fc74f8cb4def5d322f990a0867fb874ecfcd60ab80b7ef616ea676d27e35061d1162f4a710ad4a580c6b17cbefd31c9bb75a6a90be7ebbf65f1e37b459b5a33ba6fcb0e55c63ac4aa1f0851f4dd1dd0e3675e3554a72a1df0f750938458758cd9965f4855b0063c939742f131d2e9a928e81943554a3da69c3613596393920cef41bcb83e0c383866f44d2c50e40972250c59731cb265f9f9d9ff9d1ec34e9ae71c4550152571cacd4e1dd23984b0b9428a0a0f0264dfb22750c124de3661cdfd527e54d9add99b5b629441e3dcc297beab44e08d6af59c59ba100cfa519e64a5ba902dcd80271d9949995ac3865a722a3b0e77e66302c000d564da4a6db11e6a1e7fd16e255c51feed98b09b5582595908fccf1f501bf3a15701db621d547697874ec8472c42870bb4ae944f3537300235750e51079868f439b1ed20aeaea24d15783aa5022385ca514ed74830314132c2178429a2a7afc56e51b6101d7949a3ab092461f495dd58384d1b592673a865ab93bc010c5e008c8f1af0654f28cfb32864d73c483b1f170392089736c00239d392a8cffb1659955e8bad856e9a6d481347110a6c02a7c1646ff847b63a083ec5caef4d0c3fa7a0431b9db055837ffac45d61c735a05947b0be79e56efcaa9c1250b8ffa229498b5b4c125000fe432af916bb94997128bdd169935552ae05afc807293d134a3b52c98e6807ac58960044d20e2f11e7ac0b07ebe9bbaf17fc2d1fa05e0d17f05def133273b85cd23e768bb0d4b3244f5a897c119ab48b8b50050392fc36360ebd9fe144def85de8c59e05acb48109d33dd832655006de1c53052f41d04a29d7e75bd2b3a55b448a1bea3126c3573edbc06dd9f88ebeda4304023234762c1888c9efa7214240991ac5f13274e4f4a35cbb22a409e1852bf50eaec01ac280a1523a10a8e20414e65b76dd5c4b8a62e5bd62fb4605ec7c3eba069ff23c036d35d2ad721bd2017be9f5fe850a047396a6cec85a0781230d7caeb6986e8a2a472dacc339b99725e3d46a895e75919aefaf8f927e75d704222b7bb3827ca11e0b5b824c3d2ad59d62b70b2f5e4d01ffe8e8f673b7b333c6ac8fea1041cf36302d60cf2f9656488d07b00d68d917e4ff880675a50ef6aa2a7f9d007be5e3e066191d001fe67eefbaef54ef130ee5f3fab0d4107816e557d33c34d54ca20df467fb24fce4a2e0a1ad1f90ff836a1d28b7a6fe9e7ffd26e21a78583e58f14aed1d3c0a95fc8f7242f8c53b128242e29875ea5becb7fdd7caa9cfcf6a5708b53ea6000418a222f54066cbdfc70ea9dc6522df63f55335a31d45a6b82e827cb06687c5a046d0507ade5550747cee317e1b6b298c28730f0a30e0fd104409ad78962349e40332eec7d2e26df6e0db4740bb6aa75a6f82e6e3d4314678cf880a71008442449441ecaf33ba66608787ad15fd99a57e76fc13669e80cfce89128dd78b037f52ca8e7a87b6d339c86ec13c549cd9e6e6a9f422c76965312f89e27944f740a80b42b11d342c183ccc18e40f3192cfb62807ebbea8d2f9c3a7499089cd4690f07102d9b26a5f510a6a130f0cbceebbeddae9e7fc883711604251c93695a810061968137ac1bac8e84e0c911b7254ced99fafcd5b360a725964fff407fd81c432b01304392d946ac035d9b0af37d8be383504a5dd638e07c884873dcc72f9d86c77a605bac33c752fae7efbc249193f1179a72030db0e25bd0907655a9e8d19004b08891d2b06c721f240c087212a7b88f66edebd3aec99fb757d369e3659d3cc5c62ac65f4b962df10e84be351f38e4c4ae4d8dad1aa12b0f7141b78ea271ba801765f0348736267358254cb60214039a86daa081089ddfa54ac0f0d3eee1f3af5fa48168a0813e5034b4fd7b7a10c78c9b78f0433602a9d46627a09faae1fb3226281e8df06750937cbb90b80efeb06a1107742d40d44f58b3a864f84673483415fdaf8050b7f758139c558498659bcb45e536af9db75150bb72a829f3b8046fe32e3dc78fda47edb2d057dffa5b2d14d520039e732732556d0c24d34f2295a91938654eb69ce2f37f10b99a9c2b18298a4bafa1b195542a13d9a9fc28f194f000cf441ea8a03d1291c5e33c8a320b178482dc062f9c320a1c4cb8185a86ecb045861ea42b02c81820f5e6197160b647df184910c8e023b5c97ad627b2c51fc57565b127cab9bc84a42104108a4239b9520444e4f965a23884aec1f43198d8d506cdd276397858fcdc44228be59fedd73e0d94ef5dd2ccac9f46fef7a4ead921a80dc200d33eec998b1d9a8ca4ac2541a22f2908437c3fd23f760e44aa6f55f5dddb3cceb682e1c0b8c049f894784caae2f39fcb8faed3eea81c063231dc903967b49721d372499d6970f1c5e45df373c88c8618c3cb12efc0698d1e7e403bf4550b549b1426db7b4103e5fb6aa2865c29a07ac442b67803bcef5a550f1ef5a63faae8620848e4a1811249371293fedf98e96ecdc4404637aac4b92de8e453b068fb53094f085756d42c6d140e6f1e7c32a941404107fe5da375bdd6c3a44c9593182483b62bca71507afcc3cee5f8c1ca279a666da19488a6614b391c6d53cf684c123389ffd0216345f8d8a6277e0fd447be35598a8407a86995a01147caa6190acaca849e813e756e6a97ba5a9f6c081d8101e9b2a4fd94b061e6585fbd652df6594b8ddda0ca74d070cd08fad5d2e5fde0424e13f42ab5a5d412c73a6f7ee9a28a7507cbb862e332455061fac8c8895ce67994252b45c4450e5e4ac907e8b6d9d72738fbc612876d8175145b17c73b68204b57f9aa86e7f7af4349dfc6718f63e2fe8e6307c517190e0d0a3851113cf4258440ef6329e0f82be9eb4db2ecc08daf8c33e19ae021f2f52c6b75733a02be3fe5ff3df5e38191d95dab94fd8e4fd14fa2cafd6a4683ad2da2b57dbfff4f02d5ca979dd2cfe4378d970fb0968d54cee4317d100f389502a5e4611a2130000db2c6eca80c324cec7763b41310daee3ce0e4fc17bf21e479bf8d9d45d09b4dc645ae69bd27a36cd56cbfc8d594365033768d5776623688acdfad1eaaba05a9f58fb24bae0b06477c4baca06ae9090dbd9f88150507b1f7d08682274149b643c0d1dd06beb921d19db13657eddd1c3bb0443d130f401fb3474888d7a741f9883837b182b013184ee6c16bd5b015353eca93bebf67fa08d15d98f586f29e298d8776850b31ec5c2b79544e31dae872f4a739f26abedb61688250272a732d30c28d4afde73324a8028c23f8df92be6ef3790dda8c7b9f1d344701218970d27837158717218970d2381e059311870acfda00a4c30904b9714100c79dd853b2761aec0e498c49c9018c92b8533d7ff2acb0c71dd97bb69f4c982b3f88161c085dbf55fd0ebc3c9ff3a7cff371038c93da2adb0f1a4744180d5d897df01bb94520733cc6a02a5484481cd8817e9e0fdd71a22271010b8033fc0c1720c82eae4c426e40312f0f25c5748c384b4eebbf007a64214871c6f884bf95e60bed8544bb53d62fed14f4f210d7f6518b716b6d70c53dbf0702dede49a568456cf9661f4a7b375ba037971a6a00e85264bb10d917e21d887efb6b78580ec8c101672c304423f024a0b73b4950af9e8eb21f03b5f5c17c0bf945317f03fd59dbea0ca75e49d086d6095a1c0584565c96a74f0f93849351917ae00d3a6d74c6b8827302751e622bdb0c8e86c72501749f6d46b147fb6770859bb9a6702daaec579388aeb94ad4dc49c1bcc5de0e4d640af360e8f42082466ae89542cfb5cc8c82e935881116284ab2b4eaaea8b3262bb0c0869d1fed1df32a771910854c4af2a7f4875c08423a96887643cd315015537d0252894ba05e0ef5f33bf4e2455a3318d194aff5bcec6cd406529280026f4e009acb80a5adac96b62fe47db9314df3e2921234997924c0ac184140ce001919bf9216d3b996de331f0c14989df2c3fe85f11ed449cd6ab9cca70d58d9ff9962d99657b7a50d613703692f72b3aa88906860ade78a9d628b71297b20579c83dc1bc1cffa3d5025cc928f000cc21c30fb01121460d110aa81558e9f7891103c4fc50421334e0d922a3a8c8b72c7f43e48aa138d53a449c1c1ee20ccedb76c621d459e633b92db026d6f85908287d12272707955713d8813c04402ae8303714e41059ea97f1daf44f8f844412284d6bcfecbe242ba3cecfc94773977f215bb844ad94cb7f13e24a3789a1e961d956597a87265569582102c2f26a5ba904a1e35bd48b3e5fa65e4e9238c5f92940f25bb956ef1cf9b69a4a81e6b9cbc5ccb62a03bdb23f93be4f5cee324d1de221321a125af053314aba801131eed9dfe0d4f1da792d98c7eaa9f95c01283049a39de1bfd90305f5d7b6ecceff6957bedd0278770c0086cb690e7174c1bd5395af0ac575d5d594026354669541665c1420720cc25095887a1b862d3567569d3d2202727ab94e83692d38bf1c19cd1fc00ea79e7928f5ed7c8e9ecbe09fff4ee41009b60ceb810327ed1756500b1a27bdcd1f3abaf2e3bec27e44ce2d2e65a28ab9042956d8a76c463e930ea4069047fd6cee58597194229a7a24cc9fc0fed80c2eb4d7f7af9ede581ea56750ec9918e406219451ab1507965998db7577e679dd455d2db028d7eeb4c43486177fc69e589ce3c58a4474d53afcc400031fa18e8ffb978f4ae4399ee52c282daa0be054ce7b49e89c1e79046eac0f7cfe0211edc58f37b557c90760a1dab974ef2789d7c66890bdbdef400799f9e1dd432725b353e2aa21142577628ca21d22cc1fdbd121076f33c58fabb06ab482960b728c2801d2bcf86d307bec32c128875e8d28281d086e2535fe53dc3f1bb1c5a18e59309b306b637567c0e5e73055be53ef2884f3165b9f3ac8b8683600f0258264262bb78c739bfa192532c5ac84a7c65d45b84b63f1c73eca39c10fbb2f4f293c536fce16ee1b58367647c246173dca36417da2a13ac627e69fef3c50643489255726eb9f9a8fc56dd81f3104079780539fe616ed95ca62ae3f2688c237f2463d3e8eea9e5e1a87215070544da0b6ca7af5cc90e2800be029c363ef2cd37c4ac4dfa6555fe5a701c9bc8262d9ef837fae2137fbf69529e8eab6dff83bc8a73dbc293b63598c63d50ca3b14a35ef230948bc9d39581686da96432db30465110e51a11ad0dcfef9a01880b01809fc509980d84c043ce80c60ac4c421e6846205646023f143300360301e31890051e18911eb0fc61b929ff3f4a38ee38e3f1e4c82e7340517f2029d66b9c5844ebd0674df62be3b2d2bba11756ff92fdb8a2566865add08a5a412b112da0f23fbaf1625fec15bb62abd82936c546b151ec8a2dbba1e8957e5aa995b4422b6825add08a5aa195d52b910160a33420379a63412b3a4cf253c46d3fd8c9adc64fd0f4f84853c48fffb3b3657a2bf3fff332c37165544f7949537a397df3186124669eaf4b9c0ee26be559ad92b641617c9a0e8af59ea0ec1825cb1783e7e01b8c0444440d742bb70ccece09f3e7ca25a6839ecfca35ad8ed0ef2443cb3d1ce84abde9269a3559db6ccb85869b34a30b35611cec94955a1697227c833fbd860ac96d98e557b7c191c7087c2d3ac4ed423489f137a50948c7b2f831327139a78d7aa485030a8613f2c775ce0f16309db7f69501e815677deec353e48366054b3963784638e319df2233e2605f2acb09d5f3d19326fc14eaa507bbcccc7fff54a581b124c1900d10e0eabf8c247d5308e3018d5293e9b9a2aea03c53f13cd0e611960f20ba4bbd155fc85693c1786bf6abc671afabc47934f291fe9fdf4470ce3261c16cd9b1640e1f1aa7515a4edd4bc2322552708203a071e0b03171f341b082230a46c32060b28b852e744323140e30f1d083366840078c817c3127b4430fdaa001f40c2683ba729b4deda8fadb7a41fa620ae73a8cabe01479d3cf1b8db68f49a8558eba728030c36940c2d904d2e628f0ce9afdc489aaa2c1a4209e1ac483e4373ed490e9fd8f50b0227baf9059d001dc27a43138cee778c0f45df9ad8059c3015c0d6d70988ff8cb21cae9a481031fe1e49bfb3b3049a52298c4d6ae4a32057674b615eea2217051e7ba3bd1104061f3f122501d89b8e47dd140ff918eebee904e1015db579fdb8b676c91a5a92f2a1c17271a0208323bfa2dc20db530de6b78ae0fe9260c24f143051b6bf8a0c371e3b31c2d62ec3c3ba002a5319fc455acc3558f085f5a8005f13d85a1a8bd255c0245eea4398661369d8f15849b04555cec748a67802c69725d09127ad0cc20b8a9a663e20e56ba2365f38d368a6ae8e81f8b3bf2917e210bcc209b9edf84cd160ed20c919b08fec49b12b626ef74540a8c59d987b3dda896005d7ba288a8e19686883a903aeb80564894312d254f594b105a1b40c22ef41c704b5b9ace45b941b0823603e5f49ef3389ea599a76adb3452a6c9488cba10d4556c9639537471cbcb7d13c8a32fd692910e501dce9f06c9896326871fb52695255704cacc0041299d6bd601ac0cb1c7b55edbea2ae8816f3d80a303ddae7ffca428ee881e00f976b82ccc0c7ed63f55d4ee9e45ef038b24ca907c9e6965553e40cd94133ad84fe5583e514bbc3721a535825178185ca0e1f5c5b31bea027eafe60607dea96d13800f0a0155eff29afe5c726d643e4c29000abecf811e85f800e8b79b3eff19c72205a34870bef3a8b95fb5e41ec7a7798ef9841831a1e21047f2fd1a8617ac758f5e8214a52545b4b22e1c42eb25c7003ee7fbf30eac097f7fb120058284dfb302cee2f521cd26d5c6e0c7de19d3f1f200a380c44afe746c7f404f30aaef240c219a08568a1be11d6e5a7f5ff436edc78138ddf9341459509d7b2749816d389a8012c6bb42a8e0e43c7d65bf923bec8b45c236f700f1c056c456a1ce842017a8048438d4121302e168822d48b20ba1f45c8a01d65986e287427dd8e305b1053f8b94a0528a18b8f8a713ca274d518c399edecefef5780b7730526122b0a6c05076304dcf6de1a9f37da142dbe5db87590080c5d307a15a75869d691cad8d58d42e1c9459208b5df2415b8ccbd6f460f8104b25115e057c1e2f2838682192d4fc66f9096bdc553229f8b797fce531124326021a40395a5472ed71c60111d2c3056d16c59bfea95cfdfd92bdccce5799b0386d4529ce919e481f5363c12688bc0e6464712fab0361118cc8299a4f9931e3700ddcccabc50fc917014ff5c7396b5dfe1c58a10d1a53d0855c9e981507cd8ad2c0767ea664d3d90bf56235765f59e19b82e05bbf71368d21951b85b778abe4005655d1972a97026d9d88a471192ab45a0c6296e71b85ee638aff79c14e1d338f0ac6bce1ab2867411f0f78c2a41898de7bb7168b020a6e00745579c41a3f333727a1d326436248d2b05b18e1e471c8d16f4bfa5bb1a40db7f6a83eb11c54ca25a732db01df9a67aaf7b231162c8eecab767000bd5164025e50782468fed0f75214014db7a68fb64d164a0f511242bd764f8b119e65b36d39ed30352bfd79f8a78056291344fe467d6c687c86ec0b2fcf31aea7eb11324f7a6a9ee8d26d2fe6b098cfbb1be4fa5ff871d00c341bb55a331bf3eb29a65b19d3e1ca6308c4c0f16ed8d76e193ca151103c9c05bf74217e92c520ad754fb352282cb5b52f6e1e4dfb15b0ec348a02d94693579081493d72afa9ee6d7515e29e59a391b463aabe9d5bc018e9f2cd8e445cfd32d2333222eaeaf53384b142cc9d154286946fe15f39dd19f12b47d3bd21dc5200ce891984fb2958e4a9ec318f09f47c4d6f94a83d151845388d4a1b72c98074934f7ef04108bb2b97730c9752674499cfd5dfcbf6a7db47485c6d002339f38f3ead30320998cb21d2d2fc62900c8189fb492251aa08b86e909dc07bddaa8801c423b4f73d1fe9cd4108185c7fbe34a610902a30d1f5d7510fffa206cf8d8ae873bad55921ea4df57f3f2e21d511ddafc6effa07db4190607de158649a6844fae874299b6a3cfed1d1956d7365ed5d32db258f5d6ed37c3aee44dd00f38150c04b82995854013ef75d2145c85d9ae746746c622770f88be6cdc2337c0876cc65379d0482125da56f1b9cb97f8ae4721e9ede52b49412c48a27c697a18bde12c263ff16e0e3f0fdf352512b1f0fc6bfe3896741fcca7fdfceffccf86cb42019c734517dcce4dd127f529cc6982f871abdadf6e318a00545b4b2f01012f3a6c834db8fdce90e9da21daf9a0518e8a022fb37ac3ceeb3ae3567f34f0144129e4df24372e55380ca43ab67968e4e806fe3d3656be78aa36abab2836f0b48f2c80d5f1a7857915088903bb35a6c4cd87d11ab247b52e7f8bfd76f89e98618f4ca893bccded42e7468a5ec102ea1371218d1508bfb6da85ee5d99220181fdcaef9555c9f20cee06f50cc4ac9b6bd9bf0f24118e5eead272d9bc5ccc2160bc925ac4b4e4b800184fc9212eb08c789e479f1a9f7d7e61072d4d4d35ae8eef174850057b9d8da94d15632f0e51d201003abb51b3f88591a0cea9d3ac64fd61ac1afc58cc344fc6c6eba8a27689599fd0f895973cd5a9e3f0f98e2849091bf7499a5ab5c0695e1a24c2ccc35349b1dd251a17550e701ff4902b8084ea5ae7321c6b1917af11a8313a819e0f7246b22a411ef10e2895349793faa33b22faa5411294e7c98407ef2c7875bac2b1c7c6a5a9eaa809628852d63ff19877da01386b134b476071d02c00591d3f37fa26894f4325987564d6ad2953f6f083895f20a4f0f1c978f65ec10ab29727be056adb38a1f5d125d584b5ea249eef7d3ee93507808bfb657ecac2cd0be3cdba1ce0c336cf9e182a05b81b02417056622c5b99baee24453b7bb1f7c732728ba5c3467e8211945f6da9e163e26269716d0472dae43df1d2ede20b1e1404e075854a0baee3b0a1cd5a983a5a33aa2bedd61a60cd47fa510771c934e2d554b50b66a66f6e546c914415d073c51226639db9a5aac86fd29bf12657018b4b3b720cba934efb41b80546f8f0d759de722c9eabf3e696ca86b0e93e5c5407902a855586b4b367390e25fda3d5887f9a81f0736d86a1ff89a1587c96b566b2ec2305c3bd50b4ec10986e562afba8db14392de522fdbe9a09ef041a45d27b2e2caf63ea7eb30127e2ad74e739ede3031f516261183f2a745c2be29434c056674a34c6d6a702460a3d76e0aea5b94c3629fff166cfcc2b60af35aa68a4358eb575cc45f93dcd148f8e8b19f626f1533415c4c11f167c5fcc4b892691498f7a025c173542406211dfad8a402e571a9687b117d97b490d6486b2bfb28b416d15b16c04a046abd89ab38e732ca97588956454b98fe551a22e9012ad5aa4f62828fc061f06c27d744b9752ac11da2bef09c7be0695da0fd9533c5bf4ae143b564a320aa7a53180855427737d2e64ed95e88f13de0ef00804045ff94d93405adef9472b9512505d429bd6d4fa97704202c1b3e8e719a6f5d8d69a0c1db2e15b6821912868c71e579ecdba235b0d3f35c09214088b18c606ddad35939f1a3cb9c4043ed854c80ee6979798c246fac44b2e505b4c0d657a7c7401e0930b3e4b77b674a8725671a39e15631309e96d4f0ed474fd457513b209060ce8efe2f6871a0c76879b9e58f8357cbc0268595a3fd6dbde2dc38f445c386f1674852836f3710f0f81cdc9fad29917408cf6b81fe58c8a3f3f66f0125fe8b1d6c4430a47448c8310b7141e710c75ac6e121bb75467648f12dc26d8fa0310653016268a27448725f91c714c498cafdc49a0f698148b360a90407e6356622a481562c4356fd82b719e243eb068e2d904a52241ee9475b7651bfb6fa1880fdddcced9528060b8354f97fb09c524358e8466776d0741fe7029b1db901124bdd139339bdd1590ada66a7e537593063f767b25976e589b3a0e000cec27ecb1e27038cfd87c0d16a83c0832db084e2bc3c7ea32a39522b9c58c3aea6df1605accd9955fb24d16a65ce31ba0c2919ea6042843083199a051938640232810c9783aa64de7d384f1cf93873184a8664ae53a3c682ba73bdff7b63e59bd35fcc332199153d8a1551191ca3bf2b1d3a3e4c19271ef721663fa79873ba546e5795e01a1f6295d864960666ea2e0a8d719744430cc86375a1cd93268822f8c359f4a4e053b09fc6d02b455830282632dc27a2f4ec382bb14a3635e20784202f344c42a9e5177aa4c46c30e999f6f19579813aab5159ac9d1cbac2fc6cf0283cff10994846f3160f2dccc11594a0b0ebdab1e501bb918ee85064d34f0959c16250eabdda64a51e55723af269f35abb7fb0519d854974ae0fdbe9a519ce99fc31187ffa33147f8db4cdfa30a0085b202c0540315f46400071c92c981a7e27fbc9cb1ac376d92cb79d5c692ba33bb9af857226e62ce440aac51838900a64ad37c8d20bfc559d00793b5929f15611c35225a8cf3a473134038d38aa5fd1f35d09def2dc233149f913db8a37107a244496d7eb50aca2375cad8cdbd7132864b60d4d8594d0957274ecce22f9128e8f4ebb0842bbc2dc40e3b187df8cda65bb32484d8484904493bf64dd4e103750fd8404ae4f51e8e726132e9ca367b6ca30c0c3d2c364376bd7b968cfd327be25803f6b9a54eee75ce41d8540d16d975e04216db5d361a22e78fe739ac11bdf7137df158e66a1de8aae36f19e6a0869d2775b65cd26e92161ec7173a19500efdac068147c369b71cd338a324b3a533f81e78bbbc22614d98ce2b2e6989fba95447885300f48a299a68eab79f02756ede0fc521732ae75c2e8e90d50364d85f5da0b749bc5413655d640ac19267e23d6f7fa9e52fcb3dee0afe3d653ef377f2744fb7ae45af8ad443731dfe6dd536a94b831f7ba0cce34816de2b686bdd0a75bdd778286038ab4b18f76d9c2a32655e487f3a12e52844d970688d5b06e9dd48b33c47ec396e57ee7912b3bc5fc699309f2f6b05cdb5ce2f852c196914966c3e31978c1e264204509b9a300a0385bf41e9ac99ebe61342e83bfe8542bb5fbc17853af5992c1e7d949c48e96f2458b48831bb4d9673815c7a81ff7ff7f7b357a5fe3cd369ae481f16d39208ac7b50643827fb68d15f631c562324ebe54ec0895f78c20e04d30d546cd676f562832d3ee4ab37a0b5536fb0e34fd2cfd625fa258a5a30185428a502498337522cf9820faee598392afa9316e135efb1a3489d59aec963ec857e6c2386d6719dffc3d4ee90b18a10dd2481874722ec2ce3cde166b02901af1a03d3a63969fe80910dbd9c9b163e59b95071788b608f50df7f7e2f840d9a9fd3c5d194be04d53c257b57b0512bee9f50f744910e7c1ab5e92cadfff469c54d119562e5b233abfe48c77825180d7381a2b7ebe9f933c53b565d619407c258c2e385cccfe18f6926a7e4ae0ba8c2c1781f86b52721e9bf1901278d16e7ef5a40e7cea6fc05ea931004800b95e2f84da52b42ea6d6604af4d1d4717b3943bb4223fbbcdeb9ba4c6348fed0fa9f9e231368b48a2c69693f6e0f74d7cdf8ecf7b183123c82405dfa69bac6194f88b3d4f40d334d38b270526a8867d23017c91b0f70fee11532af1e5a335701931351266acfc6c253d2569003b1b71b578c714dff4fd68a08df8016e1082881f56aff6a09667a158cb50f28c6c5c50a5f17ddfe43f3b74ebd02a57b059872aa9df1df20e6aac6cef07987f944ae24522bbed69bb571fb20dc44f3f8d20b3a20a74e674cd3bd61ce6f57f0be51cb174f8f0597045977a9f1bb3aa9cefdcfe0007b0ef2bf530dc4f44bdda128b925d4739cab229c290d90dc7efe9f7433a2f29c056ac67d9b28d12b58fb01c97c56db97139ac564e4fd8e4c8f3b7b8fbf416391eb942790c76b645c1155152faac89947f79ca2ef690b67ea44f2a83ad2ad84f1b61857c9dbae958fab000a19e32656b86dd1110fb59722b8b9531472402e3011ff2991aeb38cc17682d848ccabf2bca9982d892218aa74814a3798573a344f9ef7ac4a81bb90457c3f71bbec0bd6344cee5baa4521d25a89b706cc816284617b099c5a622ce80665b3bf94790415faef1ccce5d59f2bc03b0210010c81fd4bd936489242dd27bb998b56113af0177ec7d5992dd08bcfdb521a5441c429b25bf284e4874e209ed7a783e8c5e1a2b2af85872a2a82585992b525179d3860c41082db548a6308a3a2fe2a5895eb391a73ab943ec2235123e825a8849fa4347a045282f4c8516abd041bfafc244a19fbf2e793ea63ffcf5f6cd2ae2cd524940f72bc960cec38162bcf7897aa86ef2fc9630a17ba704a5d3afad102e4bf9f1bc34d3b0cd685f4a50d6a3c0261cc4aef000cdd8301838c952d29605193d0ddd920964b77f6114a7d6265b1b39983e609a2cf74d4f9f7d46607af450f468f441d54bfa3411d507decbc22487721763e28d0e0536dc57ae9c2191b992e62a8d9d8800038ef61bca3bbc1ac8f24ff2e064dcc62ebdc696f667f60afc2484cd203cc3bcef50205ea430378a267db7167a5d8fc6d8455f4a791b0d5f68fe3fd11a557778ec85682e526abc556ca92b10c1dd87f7c83155293598c9f24eb90ec9671daf2754028b68a8831b24cbcb301cc186788d24b75a576a7a4fe3503986e739760db5ecb0074e0f19a5a627cdbe1f741c4cf24fcb58c65621225c231e94069889fdbb581d71702a32b6aa3862c4d84f724bbba3f220f8d56020efe99497e16bea19912078ba1dfab7198ca679af8a7195560616337a971c5ab1e2f6a502d323f9ddc881a45a608f4e93c31c50565498e6cae9f7e8f335eddf07eda207dcf7f8b98377f9fda86e9f488cf7c8083b6e49fdaca1d48316ad05641bf0c77c8030306b710bdd0ba27ffbf217250d126c06cc9b661f20b7a15740c355196355769f192ae44eaec70d12ad41fb5da027c8a3145a5655aef95898b56c0a41eb5f69a24746312bd66930e17d0892bbfd2b5e63f9cbaece22bbe59c85a7a47810800f1bf6cb6619516a4fb3cd8114fa2bb1aaf2ef164439566d2a369223cf14bc7a71e2428684fd318903e043c36ba3382f8626e99bd12fdf39ff9abf2bb5de1dd78d5925522c1b9c13eb54aca0d0687e0afb813d335cc87b3d0ec6849b896453c6ecd768097e5261a14fb87fedecb46dc936ec6f2c9030e727ac42de58d8a5db868126e20218ca37e95c8ac88514431f36de22b5bc411e4d0895b626a452989384df236bd04270297d0e8df761c70f7f3ff322623f368fc76d378077505936183daebc2a130f38d8835ef331ef5c9e2d3bc8aa3d95fc83d69562f910321425076b30d09cb075c221490ca6457aa7f02d3ae91591712d71edd9890e45b6f26b24780818abcc8202fe7d2ea9f0430166e5b5ec6d2dcd6e34b2cdbe5c5c7d349091f004b4f6d61583e57ff0a771896a868503301f32e82b3b59fcd9cf5188c31e847325417236b264125d9d721f842a9b1057a624730e7f04e341bc367609831cd6c16e1342851918955ac83a3feb9e4a2cc898721b6db082fac7b42a2bdad7808cc5c630db63545ed81e14ffaa1e26ceed492c5fdb0ef2efde495afa80000bd4e6288f26fdcf7bb03144886867da577d65d0a1978f987e0029692effa86057014d6f4b29e2dd1dfc590740e742d1cfbff72dff11ab3de85627f0d36261e6a7db5cb78abe83371daa9fa6185a3b5f871ad581780d634b0af35c7254655c3a9ccb81b110937ee27fe4c015985bfd5a7c2063f41079b72cedf620503bd8e118f0532f7175fa14485613c3cd03bfbdbb0758ee4d69486ebb999639d679ebccd720229dd7273e0cba43987cf6dc85f2e00fdc7593955ef6e583c803ecfaeb2b4bebc1b3e50e9eb8ec0adbd83dabbd24a76f2574f8f8b03ccdd5ccbcc70e2e05dc14bfece61a5bed5f9222e1b4386e3670f1875b16cfdecb75e99f47dda6999af02b5f1f02b72dc97cb0388272f0d49a897773831388e4a35c724ae23c47a66df0cbd83626d90fbb7cb16673af3e9c306dd39108bed32a00e2286196304d98f3ca2d62fc56c2b555a2e34a2c478037d6fd5f93079cd3ebb7ab7079e55260c3f0d5b3a8f4d75742f420c394bdf3f18799259023f435f360dc7288c8f95e699fc776590112de3b687fbf65cdcfc35b95049d69b3bbebd0bd82b3ba0da22e9a8630b01ba56e7bc8021be19e81ec13a27c22a92d4c55487623c0cb737e2ae0f3e10e41886c0cbc0b2939e488e109c3e2d5eb65039fa4fd20a0f80d612257521538d56e5129b7a59b4f8d38bdbf0d6e9f801b0bb54a07f94510b515d3d001be5cd34ef60c31bf28a8ddb8e406255ae04ab78a157c1595d488150025689d9dc1fedcab00ded8ba919d05de867d00ea946601ee82eb794456f009a2bf4c4177f62068bde098dcf62cbb57807dc4335cba50d771460a110e54ce5b885f446ca552b2590a772c1233db7f41d9fd3af35982b7834c29ab29e6b3354b70e9ad444ff0d151ae4fc31525d1d5cb970f32a0f2840f1df8555dad43665ca3aed6492063deb3463999092c8f2fcb24479d0452e43c44e1ca551e83c900f7337c83d060c28d3b3601ea8e671a9271e30df92f53430b1a5630fd50ab4fb678c9705cca2d27e826b23418faf6f6936dfd254b39a39015c420e2a0cb364706580a513c3352c972254fcbf1e8e9bd8f155a22b72f1d689ebf21257d73ea0fa49c28fcd6a4a1ab747c44d2b4fd170485dd94538abc61e77e244458b3e99e2c09481ed2325816a593ddd5631acd7a3691499e31a32c2e4c4c23d99a6181ee71d3c277fb2314d450b2e30ff8d2d1d200e1a65b5daf4a75686ce23686f3ac8fdb8833a3f848fa38f6acd8e8569644afc8ab09424dae2f04184a0a097754f40db6c9af80976f381aa7b5d2a556f248250955c00ac85a55b0adb869d0cf8c2846045478a1261ae4edcd9c7eeadcdc034901438ce5e7cd99237516c81217a63e6ef370cb2676fbb8206e8c2898f33f317eea71fd726f826b66faca550b92a9a11210224bfcecdca8b9357a970beff73189852a56b8a0a37ae770e1eedac08b0e1f89da797860cd81003cbcc1b39aa44275ab4e5c8a50534fa80dd811b3fe7a0361a9a41bde1930e97af8d0a6295c566e6d3d53d5611d8af23167e7d7cc90554309942b997dcd7524438f948de12576393d1f54b2b0caaafb511ca5a5755e6de480f1da03d3e895eea5cb3ebc92bce3c4d3d912515098bcc248a4713aa2169bc5384603b80b9d0bbd765427d598454347dced2b54c9b2d84092db48aae9f386181e0bded64a314dcd972a9fac468e232ae094dd48b59fedd67c30d38af0daccab28ae02f243dfbcdde568614caabe631580757fa369fdbb8c6032cc04406e7e92c4128e1c6401ebf09e21a9ed46e621c3cbf7e2a0d796e6bf912ef91bb98056e43a32ef39718296bcff4e7ad1a72292347b30abfe7910740b4cb04c9e34d4b35e23d2e506da7ca1d16bf4cb1b889634a2950356a5497f68112f632c67e009ccd929c2fdf67b8bb8de6094c3e736911310d545145cc6852f07d0a612049d3273226d31e29e2d21a5e6a1e534206f676dbe216877881e1de4b19d6e85334b1666ec75fa397a53a69f00b3b678a796e6d5b0ca59a339822f16b95894cc7ee9ca5d4f7fa9926547eb4f2b30cfb7f93c6f37c1740066e94103faa07e4249bac2c0055bdc0d88903e91e9fb76497e5eaaecde46b393963811dab06548404e9d60b0676532b381b82e100425f87988c18883fcb4a224f8d37a7688be7fb01ce16f8a0ec058b9d0a23996222ec2d981a894a8eff1f35364e38488f7c7dbf5927def71334f11735f84cad673ab4a95085988c713556a027a192f1e731445df81654d0ae8d4e19f7cf7532f1458d8ea5ab64e4053f015073143aa2b1c5580f564a1fd6225b31db3231fbeb305a3628f24a2bffd28cd19ee25c18c3dba46cbbeba6a8f698558d2d0c063dedf07ddb62402c4a5a2f5502b1f12e5ad6ae5871c92afecee9797adef8fea4ba7f65a9b4529aa55248802a5b49107e8f914391e0daea80b38ca8b86b6e9ee4cffd7c6c9cf9bb364b26db8eabe6dd964af819b458f26c37fac73aa69a3536b51b3dfabb96d22c5b076df0ca9ddb3a9be8f899d57572a5c9aeb37cd6bd188b5d92e9c5a8979b2b6f6c144dc7a4bd6883076476596dfcbe52eaa855a979d18204e12b0e9303f6a68f6325170e5a3b7d7889aa234c0a819d30c65edec30b4f20e5ef9f706e0486be8fec62335f40c6d020c7adf20df6737d594ab871fea9755c816fc99388912dc65d66ffcd74ce22021ffafee1b35b7ff3457d5414e68c750a963762d20d94e2ad528d52ca95a930134e3f8ffadb1677d87e574198fbbe45d0e6e90405bdb70380299a7cd7650a2992bbe254cea266d93beb4125ee65a56ae33a510236cf77547203df6976935a2f07fcf7c81533d1a7a238d080e25dafd4deb532430e2542bcfaec6cce432911cb5651ed1f3298b13c726854bd05181038f8914ad933c07a26544f273042ea93d0012a480e62bf5e0160a6e429fac11b416324b11fad91abd5faafe59364d3d18582fb3ef2595b703af3c8580c6413aa9364706e1cf8ad9ef8affbcb6ffa01bc19ca77ec4f69c8a7155aaa38b0a76062c27b559a10b72be1b6490cacdef3e4cdb6de140053549414dc4396f07556d287c8a7c7a1016691b1f416154325d29965113fc3d55dea018bf045254f098f1c6211e146569bc3e83f7017841545587cd9dfc36872b34ce2995becc748ec27e368754401a93b0111bfed060ec74815db19794ee9db989746c2dc1f6271a07cf2c6a12a8560901aa7dce4be6068a3c0d69c629cd3dc5898e15093c6387c57579a0326d7bdbcb3260d1089001bf085d3d040f7173b16d6cfabbabd3c46f5db0494311fa97780e58fbe04c553f1b41ae1aeca6569f3910929a0690961f20022295fbe18e166ffb9438ef88c90a27a5ba4b7b8b9b55d08b025da9ced87848ebea14233b305ac9575575b78e8e9cdcb1790b62b4b07ca95833c1d203a0f3890025053e41b9f81e3a0e0d95daf487d059657111af21623c4a39fea0ac9a3cabdeddea12b4c7931f6a60800fa868e62710af5585875ef4dd152221409e876e4e48db5bb90185c71276c6be28eb4e2ddf377fc17f31698b27d1e84ff5fe80569ead0ba17ba1ddbda9c5fca2586a3275aef877e949daeecd00ab075bbcb858ba3b9f9bf6c31cb8fcba30a7d2f46669927c402597628f4788dc2ed914fc4f275ef85267023fa079513d02348b3852b64c2a822ebcb48c9fc118ceab17ba4797388f830c2d5875c0f88b87fa6ed7a4df45c0ca2a6e01a191d1629d948ca6ce6dcc798d5a87835f4570d49eebe37daed184b1c11d91bb66e787e44843794b1d0efb4c0c6842d5f61a2b0895713c8505918b2d51ce4c8b433563a64b36248db0acf94e459aea897c2c92525443b141b14b9d13bcc1d27e1f9d42c732cf8153b4f4837eb359c051f1e20698fd627a0dc5fd5f2a971f9917729f3f98552fa3e8393c84ab2b0c30c3e7f42080cfe18d80068474b6e056e02ade82c36a11f0e6db41dee0f19cd5e02f730008923c12e41e111d584fa2ea6f887ffc7957b33283421348f46ab516367a6c90e60aa8d808fa8e9f084bbd81a8f939b9820def181770c93a3081576ec85172cc218328163f74b3a0cc1027837793ad064ff1449e4c2bbb57ae85f5ebd331e42d2cc126e6d2ae4c798161fd00dfae488ba002fd79440596ee827d8b273ee1480c7576d09dc090f46c42ce905c51532b9425e2153147a84f76fb6a2b6e749b066837cdcb1b32185933f8bb8cd33ac337ee0ddf5963ca88c5afc8a2d116c8c55a5ff36d8cc04f42bbac1a5de7d97392454d1f3a1c5e965531b5a8a64526a1a3c2f1da3f10b15778071bc637f4389f51159e79d7f927c04a12dbb5d699bfe3cdce952c6c94a403a7ba2689f7cde0ec5a9e4b5b53ced12e020d8e683ae15138a46ecb043a04b7321990363c41681da30d932ea8416a89d675b83dadc135799aa12f449502ecec198797a02858347ca6bf4d713286967911b517363e931f97052bd0edec48d9ae090881cb81b15a92b76a49600ae15840a280f5a65c3977e244dbe24bdff7c4bb31f526b44c3e31e1aef3f44c5b664f3f21b620951434936f2ad8d41d2451a08712ea51db663890148f316ccd37a9c9927ea335ae55e5d23194901674e6dea5d12da3d722650048dcfada2506f233d33adbff0d99f95bd2b0bf09271fd11788ee91cf210a67edc1800151926a30a747e8a51b0089c96be73ca10715e62d0f45a46a379225ec898626d46d47a84894fb226ee238acfa9833d8cb90fbb3f9234bfcead8c563605dcac2cfea48a855750df9a482b60d428e604902c2fa18445f10f6d457eeb69328ab41053900aebe9aba81dc6e7ba31ebf8640eb31d36b952b82975d36a0e0d9267172bca6ae808f1252f861219097e6b90edb1007e47f1a68342c61a20352f18aa84c6318ce91ee8d4eeab8be5aaab67cacfd1110d26025a212f9c8c08591534494187ec8e1d7e51664d92f610947d9c5b08518cad9b34489cb1493e7647a2e835e2ae4bcf3891b6b058b65fc6688008fe48b3ada7e2d93683cfe419e6a928122e20a05ff7e0327b51d901cb2efa17713a191ee84fd726a02b2cd9e6aaaef60c4bce84ad2fe94df51368922b9c4e0d795d6e4dade6c0d22473a5ce49117ddb11b81942201247501625060a8ac17bec89eb19343ced4b44fc137c203b718392f4092c6ec34b738b37462281ea6ff68306f5eca14c49982b16f64ca646aba27fe3db93e1785a289e5162479175fd3987fc48c44c3b54ec2f24ea88cc58e8472dfdbbbc6ddf7c039d744eab6b06fa9441850f8301deb2c6fb64bed5e616c9ea964a624c81aef856abac2ee9dff8fa8b3ac833240666aee9a895e8412216d4632c51ebadb8977eaf323fb73eea328a2ad370f2409a582f3c58ce7aabe15b963c7fbee65b44ba2bb7ddc7da743f46b8287c20b22d2987881f9dd2ed5928490cc96f7d6b2f03c46fbcd49a32009a80bef4578b9b1d08d98b89d0fb7e1fb9d1731e404dd85642ff2c3e7eaea9b43032cd840ded7871acf67fb76775fd80d45b7ab64362440f9b9de13bed451d30e29f423048dcf28a3a9bb2e7d04bd076410cf27bed1f1c2388b1d6fc098a2b7e9a8dc9a21e8c7df99bbf83162da7d4907b713d730432006c7042ae9a6a3a4af022c923af2c6cfb4d74560121763e7d8e1f33805b50ea6f90ccc0462990fab7cb8ec0238befdce19fc8747f24d60d8d2fbdf3e028851eeb3f624b2f7b6995ce736c238e03c3929988e98c137f24b7f21f23586e94a09a5878ebce2ff2a57c0699963fa5ce21bb92fb724201feb4044565b6c13b3f92cfeedc1d912e05cbddbd4763fc03d02e0ca0a805b1b0d537a0b9dc14961b607522529c581f4123e7fd46d88525ef7f7ab286ea24bb34656348e2281b76f067b294652f97c5d84b73cd7c6f263ea11df4d81072aa5bfffca1b273c5036bb996d084c4ec620a9d4d2cadac277ccf39bfb60b4771f68eef3ce9ee252d35c7792a04788f7c16fb94586163bf5f181039ef54deb8c7ecc54e655d2f95aa2c4a490ca2c6a92335d57c94874f13192cbad00c6aa9805674b8fb63d8269bf2dcb7c93a7037fb2b487d91819be7c29754546f6b0b6cf53bdaa4c8d0d1f1ef063778144c97e1e874ec1c43e08416824187698e53ac40cb2d90bd8eb5400c5541a3b56eacc92a6fe71f907b998bf801362c4d69d1271ec28b1ac0e4112449c7896263c54ab9f3ea03d5d46bbb97afe576fb90ee0140f63e55b0f42e9e2a5948d4ee4c1b4a257dd7b69b169401ae9f0cb69041822c45aa6aaa142315b5752e1a66b22855771e0a2e464baea70706131a6c2e4a686a13854282a3a352c492038452c46eaeea11ca780c2a16722ac559104a0d60322906949d525162a302f907b3ec9aa4e87a458292c06f2602afd3811c35b0092f42db7a8e0c11c75a8c650035bf1900d56b4a63b618307a1e2481ee404d21a68baaf87c83163022448a2a1e4d95e44269c0e123aee00269f5f01189d4bc53afa95a2319470592e1af8bf712fcebec758f58652f019e72c5d8235682bff5f8fead1e85f69d63ef51c49bb3883e8a381a9b18f951cc614d69c2f1b65523fa2862a86105bb05610545e7da1fed11215457c9a3e05767a43d6207761c54b967da23563fd9cf5860ec5f893a79dda21a1eef6d9acc41adc316093c1e3ceb8b1dcb6c605bb9e26b1aa2e662ac578ee4e6ac5ea4aa00d317d032df18fe9157a13d62cebb3ca091aaf1bd542b52b022ed0dbc9cd0228f98c18ec57745bd504b049ef37f788d4076a9ef204ef458f8e5c4cc2255d641b8d43b4038c1fb5666956b3e860a88b6e734485118fabc49f81ca7fc963fe51c291a8fa78ca3d06fdb20dd2738c814b0fb67e783cea622c21ed19d621ecb2751a372988089ea80fb398ac2a781bf72c6c77763009cc1cea7621fee1edbe1dba6dc2dd8096183123321a0b5f151b88d6982cbe4a0f8df4ca4c515835f1acedb705ad357fc8a125035c83e66702297264dae6fa54bdb1d7345561de3eae9d8ee7554384f3069cb8d27d49aafafd1c7bc65079bbf61fb6bf3b93738f91fc7700a49ec89b57f669c88d35d1b5307dc1b6213ba04b044af87c61ae109e396193285e89b6b45412ec53cc9e8907ffd37c3e61080cb16d370fe673ae0a99e7c763e2d7be9c72a734f502da30825dc02a7e41e0cc152daa037c512735406756de775186659469cdf9ee2d1f3efc39906a352036b9240ab27a41121de2224f9d56a4345039d211d550ac5065fa1ffcb305aeba9d3dac090be9fe3bc9bdcc0284a82aed906b3d90a14a5592c698501b92969a2987f1832c38730dcc3516465cd911f46af875acc584ff22f158d43ac8063353dfd61e81202d926aff6b58434dab241b2d88c77e48eeea825dd77a81969ea672e6248c1fcac1ab1154c86041287debc2a4dec4e6762329212511fa3bd1833579dbf932606b089c6b43915c5eab6646f3a08dbc5dab56613239c7179f466a1f7a4c3d792447b86ca7306f58cd15406e3b25600d88b19d49b570decb677c1079b7b8f843f3c9e9dcf44c5ddbae8aef6cac9ef4230c1a0655ca4df0b7ec82676588b85ab970a8cdacc6188139294187f031ec0190839a8cab5b47523007de666852a8221a7dbfdb15b4a15f64f80df14d8ab275b520ce46b2fc00fc7799d2639c5505f86622fea8ecb9563079c07f106a5fed4a650700ca4e8aa35baf5849a23a4bb0daa6e09b4f33e545e444e6a9fbc1d80965f93dbc6c21b3fb30aa28e9e1a360e913f684e201054d0e48e1189a60e7f4cd3f018072d8947cd262461778d53b07c26bfad54f39f78027e56ab13392e15757eb8e4b754a64cf185d20bee8e6425e1db1443e77452100c99414af312340198e4deeff03b8394186c83a3d5cb1af7b85c5fdcb4379e56b30ff8d43e9ffe635127d2fa96c8772e75e0436ad92538c000588050fdbd291fa49ebf9e1dba3a200032ba5f3c44d875e26c33683f60067384d3d598bbd9dd8fe29cbf65700413c27b65ca7f07208bf03ec17c80cabd21f5d4b4e8dadbbaac2e485c36742d71d219e3e8d2819b6f5004def4626c3e0ead3400338891f8e778712bcf5ecad536246c78f75afc55d052236e5cc8a92fb0bed3a89bc58782fb19342de067a2d140d94cfeb4087054eddb13c05a612d101a1d1e5466432895544c9a98e47f8271bbee014d82ffe273416946d43e0fe51ad57925c9ea2ba8a6d1ae75f612b8b45cb67cb1959111e7a2c921d29f7411fce8e63f029f36d040ebb024bac304288460a68b537061280ca4ef1e6551566b3c2b8156055bccf9d17e0dff416b20b62b269c3483431d0441d8e5bed023493eaf4b179a64a9d1d3cfa36361f68831c0c11eff51ad6af07731d8e90c062b1a10cf4c8f5c31da334b00df77e64c775d2840ddc487ec34dc2238b8cc8734c61162e59ef1751964c78a803c516fb0bb8199371cbc5866152c63dd4214ab30526ebfedca15affbc72183fdb1ec2cc1e327dff4b58b260f0056ea21573f0ac06984fc65775e642080b5777ea9157a1b8c3f2631e63892e9285334e99fbf08daf96c3ee2d82470d8bf246bb02c9bc7530053249e6aa39a8a9b916675eb084195b4dcdf3b802cdc04c3fe5d30d63dd8acea5ce3cc34a1baed1702a1c67e6c66fd865add55b03313278e8155330de59c20c76a6a5a8dec148d5451c436bcadbd327c2b62bcbb6429081b745941e141cd5d77f760af3a49c588b48c31a4dac38118ab41fde27caa96124b45e995c4a7f54ce786f849f9f4510031937f2ac511329a51f2f60639d5219075c711578857208c139a7e500035d0c999362132fc67c71dfa8a628fbc94253e9f7c0ac2b2970e390bde35440218102b32eea647ba6f124fa7b8bac1ef8debe89c97453b46cd353cb68e43404b351e7a9a495b3eece4212f9a4e713b577495084a81deb939ec68140868964c283ef7dfe03ebb18c762540ced31b6513924384c3a31ba4a43bf0da84fe1e94e870033b672faa528f5d8f520413c0f2003534c56402326446b021ff91179d8378f4aa790f59e562176a2f061a8aaef7608218a17d63e3cd59bbecc31a5c849f194f3f14e8ac98ede038bbd15473e06a52e910638d1e2a36e1fd27eda7b7e59349cc91fd2183d32a7fbf25c35cde536569d2203124f6fdfd93a593eb3406e9ca7892c77b08dac0f737327922e4d700600bcddf8ca73edb3af7ce7837d655b86e426cf6f2e24c5ca2eb9f28696e3dd76286d1273ffdf4d2aef5de66f616e543a60cb676547ca06817558a452d8bdc25606331e5719e6d5eabc0488e93e137884aa07565918943a1c439e79df489a0373199fea004e46729fc010467f881461968d6d13dd93a917b9a97fc26e9d79b8eab616dffe833ef7b7ed90dc12e72cb93c30cb546bb0127a3a6180321bec21bbabc095e5e0933e5ec9ecbbd0cad5de37a5499de9a98bdd4d1146d4a5a353bb733b71307e807645b7287d6d9bcde83ccc943b57ca40b0e099b667153ecd03bb1097ec6f5f55b14a020d8966e8786e26372ca40c3db56c514e06bf9007cd635831d21ded8c110519cc31b6532c33ca8521b0e1740ce435e8c88846bd46769b35664ebf530ea69309a722b67c1b49364ce11f400831e138cb322dc4568f5a9d39212ff9796f8908b28b2587360d461b3b9082a636fec836141ec698b52d628b631c5ba02c9fa5a7c1f9422265fd23580780989d5723a39fa3527851176ad868ca73d3f06190609ea1d2ccd67095775983b6a479b09c247b1cb7b5a4d57ffac3c97b3c8970e9c5f914cefc5573a784385e86a8fbce5a5aa5f988bbe9b89c649fa71c9dd0b52191898e8db77e311e474ca42dd19192d6b8a99dca293921c6a93044766dc8d76c0295f68ca66326c9bb27aa0f362060e59c99cf0856dae8eb480563cb994b5f25f084e8193499a9efde0e5e6b3264d86c69bbb5e742d763a2daf62d929f7824c8ed4e0658ea9b3f28270ed1a3b7e79cc5f3b9e66e449e127571699f42430fe4bce76410bf59c4b493f4637b3b3a003d88665160d58b2a3ac34ddc81c8b07042af28690a4b2c040982e2798a2d9c9909ffb10d3d4674350616e9f16a2ca4f1510efb29cd93845b7dc8478940b729efa7b9b1fe56cd965345731bd860dea8591b4cc1f38edc4a840bff6c239e31b54bf91c9c1bc257ec0ea657b247622c7f85080720ca33fcde19f8901f19ff7f207c785ddbbb5879b6ef96b61f93dfa22b28bde48a48a57c85166759892f32ac2ebe2c61ddbee205e3efb1f054d34a25de3c89384ee404c5a6fba14cb2bb1f2c15684bbcb29e3b09c6e8beeec495384157226efa905c5f351a5a7ad5f0710ab44cb1ffb938cd0c43ba226a7287de33b4f1735c131484412fe40d4ea327cd12092cd79f7d28769dcdc10c86497bcc074a9419a101746140ef164844241dc171ef1ff4ea4a3ed3fb7568030ab1bc29cb99b816f896ba35fad72b2fa9a76b29db03e599fb94b9dc99aba278810c4c118265c4b3cf2cb58966ff4c6a372c7bb6d9c769aec2dbff7a93d3fbd2923b76f59b452eef6c4dda78db1c1c9e577c3b4544c2d00628d8498fd923b9f2b0b8cd39b1e053f8d4df4092040f4d38a45126bfdf06e395f505bcfec7ce36046cf2e1c18eeee3afd9fc8204f8fc17c306cbab059b0496491d8412579880cc382a24b6f7418e03dd2d3f25fce12ac62de50624e62d636d0ad4b677fe37c20c6bb3b5c63effff8048e6df10f7016206f0e716683e35177b1e9db01dd61bcc08579e89f327f9b18148d477ec0c8075f85b1306338291373d5d15c03bef9793e948aad996858ea607bb6d83e23a1b87a4fa819709361cb9096b410cb4ee931be962e0dbfd9478deb80ae84efa3b289e0c7f8e8602a6bb381047c5c1e04a881ab9aff6b106430a98a044ee698dd9dd4e8b77cb8b3f2f34e2461239268dafdca3d0649c9c8dccc64ac661c7a5cdc9b4e4b3598a6e35734bb9703b356ce15ae061bd38f537e1b141c3cfea4e37e6e61f80471ef3b009368173b17732a97ab91db4842d36b108854fad890138746227175a425037d00b0f8548e2408fc58f124e04df6c967cb70efa1eecd538093e2dd2cf207438d4ffd005c39d8ca98fcbd7be51b19034f05e512ac7cde39a283ae50af7514e7db5b26f365cea8d5faef7789e292936ef7a1ae859460d9a3d0d45aeab052c7036125f5ecacfec447fbf94b9006d61ec902a6b6e6adc7ecc46c12867f67cad01c36378b6dc1917a0d7872c425df42ee8088af3530d5733181b39c5ebc40582d3710462341a62e9373134d62944539e16536f83b664c019a6b5649d926fe5990fb381d33adc6a769de4d73ae4f703547f909624f9f9c26acd2a3cee2da54d218727ed3fcefb2a09b8cbfa7bf03b43b02699b3c429b6254eea7a26cd2fdcd49ba46c48b6fcc9fb3d12d6e75d7b55757e62220822484b9c4e42782a4621d25c3cb95f243e448912fce8a41026abd628a2f2942e9f8d8b1380099755f61643386630c6628d4b1dbbdeba5d68f2a3b5789852c63da24040b9e5ee2541452fb11de225926d97d87a35495a5276c651cc0b1280c8e6f6c0186f7f23cc15e2041b7d1c24f538d4f6d7b0aa73e2e30c37329a9c49aeda8a09897807cebbbb213319fcff81b1cfa3df28a4ca6965318a2742b6e7ce9f928f26d6eef19963daa4068917be60b9600f735c6c1e4fcfad979ed154ce3f3a00fec181dbf31cdf896bbf54dbab32b05677a4bb5954e01a11073d9644854acb48200df7ba480f16da35ec3a1b8f1868184c2346af4efff4babc3ca2fda1eece2ffefe27cfcc14fac298e6e8ab30c23dfce65791f49af1c07b1719db5d54976b65d8e39d64e920369873700afedbb7a6f8b37750ba15cc712edd0d74ab879a85d0d97bb056965bf3d0c966336cf8317370648e4e0a6859ec10ff2dd3324a35eee9787d71607889b8941a58e0a2e101702ddbb26dbef0679c9507d0485418e33c11e9e70b0d45ef8e77e8f7d181aa05b2befc6d711558637904bc5d5a6d5c2738f89da4947eff398a325873d1998cd1af96a4d6df2932ff789a4d0af58b4e2116a8e80a8cd5e5df644685bdda71d47e2714bb4a2ba932e921a80a0ed0a8b7a8f129759b7d8454e0dd7cfd46508d552c42f892b386685f1c64071da6c99e0050b0f7563df909cdfd0d415d9db7452c6642e35b008d230b4ca58eb88af712b9f48d4d8a77b5b0243064c9a24531b0bcce691f7293060cf0739dc431104624a281e27c1f449715d9457830500e048aea829bb804f0b8fc25ca488e31f1a3733f98cf6b985fb8156b17e78c083cc80db9ef1e868b679d523361771e90341a5d3cf28f0fe7a0aa618d9df5585907bff499e1232fd7d90d91ccca10eedab57567b788c5276d94029ae0e64d44d221ff89ddf2f57a38a5fc3de3aa30bd335847692ca9222e265421cba09326ade1eb1c79e265a9edd31cad8b9fe20509e66413e9babe129c619932de06bca8deb14cd903dcc80afb582b386c094cdd5e53b323f29d255874ead2200019bd5fdc5f629e6d66d642474c97fd69f3b828a12ac82de16455b69c363082d60b375ef548b13e91bff6e17deb970dbec39c6de1e3eccfb47f4b26ce837d12305e5a2835fea161100b7b14d57042d26b85d8ad4d5835aa8610e939f9b7867676210487181e394658e7264241c988209cea013ead3f5c033e018c7d651d8f9638e7a35c19ee22fcf414fdf7273ee86828cd1e62be99f6d4b43a85442398776da2b84574a7d6eac8601b5265861fbf454f891b8f29b120eccaf366fe297e55a341e0e0b93c5611aff8ec19ab3f6be042fb5341b67f34dad304e90d920c9b8f7e375a3d3a0401b6e7fa66ee41c78115d77283df32f6ea12e799b09c46ed2e02cdcc765e07d212ed4cce522fd728f2fad9f4ad6dce69feb2680a372b10b11a286961f8358993f646d3d0f36c54ff4a97ab9df2765e646aaafaeeb7017c58094d94ea33682324e08462a3cd02e3dbbdb2c3de089925b643777b6955fa085205317bfda3b3beec48259cebfed2bd37603eef6beff8c40ab87d2781660cdb53e813adbd67413cab9fa007e5eaa2fa1cde8c8e9aa3240f6ac57ac780dc988936bb61076279cc965049daad7fa85eafcc9f33a5651c990a03ba66f5caa276665e67489049d97922f1da597a9d2f88e021196e74097dc13e19b5148bc62fd10036ae4d7f23a8324fd07bfcaa05e85a0cc45e4214d8ac57537098f1abec0fa386dc5ba6c5437814a719386a39bf4deefce43d69f5b768bbb4cf9a85f220649525eca3f0f730014eca5f470fa1defcc82dcf3787fee80fac5a772919e21437d3e4ed21e57c0bcaf1d7c6c20bda426cfbeec1976e08fee3b54bee9108bc3b33076eaa5628e9732e24069ab045661a0228d791348c2c4f9c2acb9e430586de4346927330f87411083516ba76c675a9b46e34337a7ba341558257c73f4ed4354db1ba68b688098a9510c48267ff88a3af2d01a771ff9a33e68e0eb4cc7ada4557fe08eb859314062806e86d3beb5d679bd687dd1aea35a14ea715a441029071c0cc1c5932eab8718f1e1dc7d9ba855443c2d03af81ba403e97169ecbf06a7073311f3e3420df519cd14d7a60d828830ae08e45e4d8d4b240a18ee81c6a4fa90a6ebb821a2733f4117e26890a4abf99121cda2ca5e61117ccb7b33b8bc3765dfd58426f4c22cdbeee461afa3ad2f5e185cde03bc4d5b5b78f869fe881b77c6498270adf40df18f46d5fc232c93a075ec91b7e43ea48dbaf871657a641aa8e6f6d5a58085998da705d08206ca565339535dd46a7eb9b06d776cdc17488a7dc8d4a92708a5b3d3aef88ad98c317e5e85be170cd52b884404b3d5134ef51b7604a65ac06743daa8e018045c5ac6709c6609b4f230e09178d444d595e78a451f69fb6485cc2613a876384c1bd9aef7f4fc520b227d998c7b10ec1bffa252c7502961ce2571fcfa66aa27e8c5253913dc8630b20199588c7e1f025cf5af1949dba60698e5c23e9904aceef99a9fc41c5516e2aaf8ac35a9946119fbe75a21aa6f1e6586987742c3d4ff743e8989b0c5d0848317532ff53a15a8cb1d6ec1ccf7f711f9e6ed852df31069f659ac089f052f3faa242fe7695837c0c8dca8ed316e6deb1366781c3518bc4c0046b0af48364ecb30acef5c47c2744235eafb9fe7882fe757952ee49ad07c724af18b4fe84444261d8e9b059d60577b6312c7d35d49cc49ed8f3a8df15236aba79cd5454d1d97e60a7e1c89dafeeaa3cb265e76070429f5a61fd550e61099822852860da21da0eb5e8dbec6c72e5c9519c6bb1b7c6d5ef665015e546e766815c0a3c485e38e1694ab4ab49c381190484659e6e944f094eae379a18a30366a01aadd61b1e3b71d0eb878117f451228327bae9e6ff47ae95116c539e44f6fc1d3e66735b586319df551c30b39c1cba7510875dc58e2a30d694a970307569770ce41b50f6c0bcf5a80c8dbacb3ea0d769cf3420b1191a6b1a36082542db1c883d574fe785b1d90b497ae0f1b1b89c4756a8af8c59a3417f07510ec194b801cfb771366ffc49c93d3c683d06249f846292209b1becd4151e7efca0463f53983bfec7ecd250050048e29b42a9906c5e524ca3f04e90c1f56f13e37d04afa700a806f0dea03741aca5c0a76ce1e0ed3276549216246fbcff45e00ea9e3a8040dbacb853706117eb9d410e903f5c0ef1f1d232a00831794ceaf5d282e31ca7a95cd84d1c33792503db3252f0326978b81938810875749e265ee7eff36104e0c3f3d3611bbeee78260b8337cb1d1f5ebd0fe7326fb36884618809944a898df61ec36f16c29820088a0862006a9a5c40fa9d7ec0795e95ec3a3c4da53068f8e2b15a334d4d272e4e261a59a921d4b2502249c0c9ccbd2f7e0d48b018b4c400dcc606758d4b06ed486b139160bc722fd66ba8d5890c507bf140b0284c8871e30d67a58ea975de5b7460e4501a591cc1723e23a835b4c52867cf05933a2a1164db9863533fbaa8a94b4ca11f9f859e3cc210cd65e0420f9ea4ce1efdf9f3d4f8fcdb71455808de52ba7d1946d701fb833ca5b7396a6c928060b7b049897f6ed43fcc439f5e3298414e57475cfdafc216f4f98e0af75041d49d85d715b1289ce6fbc66f0deeb962a472e8a47e3ed720e4e9978cb509d8f4816750f3f54cc16f97b9b710b89c7e68fe62eef1c73083a0dec89340ac0dd708f1fccaf70661c24e2dd865f6282a872c19ac474b92f8c1d3943ce6aad09c591eacc9c17cf1695665d9b6ca93e9281fa7fe7edb9cda968a58793085720b93f0d340356870620e54fe855ef1084de548658fcf1828110991880e992d49041623b9f5c9a22256bb5c54eb41a03d6fb36bc4584600b9fd311dff10e3a4a7bed4c11c7d643d15633df67c612faf516663d6b45c65df61c8f0e4f48ae1a484f429f41b094303ce4567fd0753b081c3b43fdb2e9b653417febf63c2063e3fa84f62672012a5d4ebd2354c614721d7447cc0d8635832fe51d8dae67fb545d8cb9df76dca89f6826ca75d662c28e45d546f3e91ec7b3efae9cf4f7383939d020cede5bad1486f1afc7b78ceedcb14763557fcd5d0406134ca78142d3a92dda65636a37120c5722b4d7569ea92a2aeea9981484358eeca400ebd604a44a907040761ebd91b2d38c6523290822f7f515d305d1f11db32adcce296b9728186b63427f03c4ae6c9e01df5ab950a95c19ab32be359e27229ec54cbaacf594202b053e15dac56451c66012b6f052aa9a7d51bf6aa97925942ac87694aa0ea085b51dd2a7fe640229d157fb2b6244662890747d65e279f3a198b7e50c682da7467ab6c55d3cd344af1b0abd755eb9705d2af564a4f379489fefb2b6e94dcf8e0d36f9a7b6ea9d8d91119941009dbbebe040d3cf6a6b27b29a8d4b65876c288feef1b5fa9fda0a2fc6b191331df7ef49eaeead71e23eaad545a3e3df8f805bac2695f86756db71970a2ca5d7aac49666180f7dce3c73f34c7bd86de2d8fe2fb0709257a9343d5a7d9a5464ee970731b4cf116419246c1d1fd492a47ff1ccd14f14e9c9cece0445d1898ac44e548676a6257c9e3acd883a3a1b5494a102c237ce785f84f31d56824d36f473b5dc7ee72446c1a9e0ef632e1316ed7f8b5f2b41e2e413daef82faf83d97f000933945a52e4cbff76281ef3460b76c8d27339dde5b2f94bef127bfbca0ebacc077f9c9951d51036d577204b3a46f669a0ad2f3f8ea381f3151a8c12869e3ba70ec622f1e2ca494f1d507e6e854986899b4367de7dd474982be874748e3ba4e4383d800fc35c491f5826989a605fcdee5e9fbd458c8048621be5e6f63cfe3dc6e6c16fbdf4d3df9385386cca2a90d3181f8b50f597526532c883fa48178c9f6b9ac94bf479e3060be0f7dc5089897ec93e8bd3f0bdc3caf34bf6f7e14b5ccf691f7335a8e7452c173a5e9df4691f53b87058a869a06be36bf708a945edc6d8cd201fa9ad6b38990e511f6617136f964ea269eabb3e39906d3c3e06e0670eed7e382cc9caf98851d92983d1e50d22359457523799515ee1ce8afbb346a434f3843c28af507d800222a29bc229b1bfddb097bf4ac6f9b8c7b0be96c06f4f533138d132125062a93116760571330828e15a6a2bca50ea14cc089297e41e0b3c99424bed11232ca47d42d92b011316cb853af11225e5af273d9a5779ede0314909d578c35cf90f44ca58cfe4297f3d537f3fab83581af591618915a8afd40a1f81c43e163a3d43ffc87fb9b32fcce07e6b3170f28949563408f075542fb54f2bb28a2f9155b49758d445c3afc78f19ef798ac8338c2f46561189a4bfa8b11f12c04bc45961db4da83eb63db039d5cc5b57c853ce146f1a9f484a249fe303794efbfc598f7ac6d2db6d20a29081774a790f5f950c4575d78530cc95050ec8d96d94f7d00a90cf9123809cad1765facbc0ede6c8135af086ca8310d401fd8c6dd22e7904448beb40007b089d9bc7b71fa55f41f744141f83f80e411ee0c3a21ae1ca1111f511431da12ff1014952b49e639104b51ef7dd39703e7637a484ea32e1acb31e64cef890cec7966d6b6c9c1557d44def8ce44f0f541c7f45b0bc047d4cfd2ebb78efe2ffa08f917d270a34a7022209906cf47035e69743a05dc12ad5916586501d4aba39b8a302036565e60c0ef08fd1af43b99471b05deb2d259b0ad7463a7922792e4311dd49852e1954b1993b8fd10921c68f55d81d534a8d4e832b1a2b29fd040d387466689a84fa576d60c2365a9aa35a60246c46b55fb75147de6280b2ec6baff42b35c1ccb577f1921edf3c32f3a3d6dc72965bf01ecd27be641fc9baaaa6bc3e163a53870d8b89a1328582321676bbdb80f2900de8b292c98b399f781365d3b6a2a6e6366bfb608661083b33c2240e262d79826e99701108d3a6d44b9e076b50388f53e02c686485979fb88cdc6d77f756418e4b6b8b72533148247d97f48c2631a823b0a9808bc410b511f7ff9a3b599156d7839997ca25eea08ade99d4f76582556342a40351299f250459663b1e8733016793b083ec2cb7d7945bacb8e9760ea79205280912d70596cc4fc01123e9089b72a6e873d1381e2027c879496b4add9b39e7967535bd0547e271cb4d18045d0231fdbf9de95db15d131666256ed2b3a6bc7bc5ca908cff3418c59b6fb12143d579298e5fca9f1b77f55e18bec825b74e5d4bbfc0fa067450defe649fccd7425f8f6c73a6ddc17ceef8dc66cc8255e20592583694e9bdab5135d88ed311bd67032b688d24343fd336c69394e77cb608789b8f412465d36813ba76e94103792c21f5b8d8d462a40587637e004dd76c0405d8b45ebbd69874ea78a6bd4039dffe435018b5c283ec1d405184b609f06863ed5f876019d7931f97159ccfbc68c9622732b80d7345633df6479555014cbb4418d1cffdc0c77978cac43e047a12d5814688601c4dea21c685a025185a29170ffaab0bab749bd29ca95ca4ddc94be67626f23584a3aeeb7fb46cf1fc72041ba8b47406b31c533b2b1d279f83a15e8b95483b5123ca764ed3a7847b9a76403d01583755eb478e96dbbfe14ea337d2d2129d75539c70eb057b434fce3bddca4a8140f9caf168a308815c89103ae155f117c70a06abf5caae57e871b1769bf5f359fbe8bf8441d70e4f495c12fb030971ead89d43f26e04033401a5663470925a5e196f2342e5918613d335847f3dcb0073d587bef142d5309b201813352205f47b268de0749c191a076ea58545002ff18f7129aa2c51dfbd13dcd7872c43ecf21e4da234e2b5b499ca3f97982b6ea5988abe350eba5ec2d2f8dd11a59d9bbcf1a41423e01c4e805e294e00b532c1d261748a5e69a3adcc961273fcba1f461c593aad69cfd68153925a30212139e6bb4ca644eaef3bf262df084f6ccbc1a0402a162fb79ccf6c3bf52f5af26bdd0d3720de224026de142ed3548f0b3dd29b5037ba22b8cf1f70f86c0b419509ea02abe3d147c7391070665e484e612bc3c46da162a32be92dc838cc94aa80201cef3a74bdb3085550d32598d86e90c15d691a31e5d470c043ec2ba916e95e28f08c1053d63f7ac7b7e360ef1a2d34754fab3e1f08bf0bacd53aa4936ad2b8df3721663f9b201d1c69ef0f762f361d1f1e5945ae8fdcc78915317d8e9f032be87f010c993f2d54715a740168183bfe0cd1b903454b816e10955797ca306ed11aa5bdb31dac95a115556ea5a78e2c909d8ea5e9c530520bc3efe8494af811a7122e4fcd8603e743f5fd92a551054692d1ed5b64352856d8533d1e344fdfb28e70b6da3d44be41e45be94167052262138e4ad7d97e9a9442d56f68db3fd936d7ed626a6ed25a89de8876bb9e19bfb3b9142276ffbac8bb29ae843bce3ccae629453c40fc13b2ba014bd44da37d8c504a192a6bac71c975a9906cb939981ed2402d840f74fe93102b5f857bd0b0860dc69b668842a8f94ead9d1535d7a7dbde360a145ffbf1352cabf874cc187487358ee0b849f8e7f8a15e935faea680fcec72a6db39a1e28bcc3f541f5b3f5a62abe4be796c1371685d5a43abc05ca8a20cf5d93a79e55d88b10f3356cca3307c921eccbba565f65527c62f1231b27529ea84cbc4b643da256668358351eff5e9752d47517ed255137cd01f1a47567bdd26b5af0b3a013ca7b114730fbb526691ecb51eae21f93529519a34bb3af40557d8eb6515cad246f0ee6b155ed4f0fbf8811361148191278cb3cda072caa5ee8012ae07325429070fe74a69fbeac9c560e3929bc03bc468c210c11bbe9f280507c0a54d924d92b1aae581cf064b491a9a05c10a4a96040e4a8244c167af950807844200861e3dcec7912c905bd0588d772e68f5402f4e8e53933e3c82d82589eec9036614cfed51cbad7ba86f9b2d90050301d0817eee139895a1b828ffd115e886693f61a0b351a84023506e6dd1bba9748465db2ced7d392b038d79f385185a80e4e7580a71cbdcacf34173680127259c267bc001dcf43ab7e7a4bb4f6caf63990d316b902290e9fd35c36df78711b07fcaa0d192c7e09bce45d243629c0c2afe0c1e26a73d965ceedf9fdcc70ec2bbc85f23d71121cd8994bb267fc7aac078bb504e0aa880374991bc779c512820060d3fd1279e4f8f7bfa532bd70abf51ac7cd752d295875a010e173efdddf7e2c22af0d4f8eb7efe24cc59a850a287924b48e40edf5f31761fcb9d9d20f4127fde627c9f5c15c519445bdceaddbb3d7b641aa4a5c4b38b65adc347164cb41cc38af38ac735eba198f23b9020bf6f9bc37edb31d21c39a3df8e2f5396004943f685b7cf103f4041b8f8e07ec0db858b819d4702dc466198cd886046e0aba6b04e6b3239b0638f00f1a7baf3e54e0c5b1df1ea185d72c2388f28f58fee17d495c28ecaa798844ad17f609944f590b44a53e8a9702784ae4ed205518600a590b7af90d9e229b2ba1373080cc2c38b7b275a699683ed38c15e418a11e17737a80a7026c81b757ed1b9f7367abde9154c418884579622516981c54b24f2ae79d83071971768849c3bca57f78e7193b1b05982eb52e7e2ce8d05167fef3dbbe6e7e623c4a2c7d45db2127d6d11685c9528494ab14a2529d2d838a146d2260d2c66c25b047aa04410096f0c4ad968a8f0e6f81792e77fbd264c5abdced4cace2dd01cc1e179f53f1364d888125a76c1a774324ce3431f83896725c17a29b784a843b538af745560484291adbc0dd7735ffb3d0b20c0b9146569ab237cbe821121506555e9aef80c7db23fc9ca9905ee2a99ff7921e0c563c68438551a5d56e080e40fa6bc9efb5bc9f31a548374afd215751863d091d6ae78c013c71538c630882c2cec4f0c574142f9693cf3bdec34dc655646f9da4dc534a06b7b5099b3c4748695f69e11d8c2515c9bd7038a14ec284edd36cdc380343e5fa17ec688417161fe843b7346f011937ff039fb8f108c25aa1d43dda09b96118cf5e97aee43a97ee4dd106071e9341af4bff2808c0b16346ecfe6c72c75467473957c57b46d3ba9e05ba499557fd8a4fe195ca290ae5630e0f0502e0686087906cf59e0eee9d13e28b948222b4497a4053d1e06626ae4dddce15fd902d90cef596b89327bab92874d413c8ca211c8616b841619d848aa2d7894d156cc65daca8059b83471685f801f34c495b4cb0b0dbbce50731002d201c297e9a28cbe2b0397abf44842acd504af477060cb6d6644690ab8c4f278f479d912f267c4ecccdc20567de85c8ebf231e5fb55f19e720db1df0853ff09deb9a58c9817f48f9abf1698007bc7c050e8e44150e52202015271d59476117bfec8a82496e04f5e99da1259c64d1e567a5f727a10cff4c13bb32cb6008aa460d2c902db64eb0292a5cde5117c76f1576ed42ed8ace5ef40afc9ba1d53e526b84104208217b6f2977430ec50d4e0e32dc4b95a30cf76853a20ceef1bb913282ab3d6a31cae0364b64e6f08f15ad7a15b2c07d4c00c37ee9a677a43e63b8a6ca409583a40ce5ecb704908a261cc761ff620086cd03fe07eb23979e3e95ba1c0753a394d1b4976315ec3a8ea348b6d3cf6ab76316f7f8d0558f8f928e030aea22e84ba75e005d521eefe82ea2c7ebbdc7748d27a5a6463546ead21e4ce3c118a87ba8c91261d61eae66354de34af605fc0b0872424eb8584e4e4e0ec7712f594d03d280388dd2872824db3bae8db40cfdb6358f4c027824e4ba6e07f79b2ea855dda803d2384ffb67e36d94b3dcd3299507847c3a3d3f69d57797a44c1f453b3cf0c115f1a490bed3aa164bc1910d5bde3a2db5773a450f01f03a2d6f1e514aa791aa0bcb31ed54438d5a912475e95b6aea72da637c9c319de3befd485d20df75c9c172ee2cd6c51b72af57671031e30a52e01c39d33a8874475b354f94419b8785b823dc10c540a59bac105e95585c3a76a2599116df0169da1614236643ed9d6520cfb2885acec2401cd4c2adbcb04072a6f4633c4c2f5921bc3259171a1b52869e4e81a607c662da4bd53af6fc20c40c3e82a7bf5466f1910b1eab61ea625c5785cbfdf48123ec2fef5e4095110672359c56b8dcbf7aa3dd471605055b5c8e3bc7dde3de75eda2ce1bc1d3a38d7ee95ebc17d1cb0b77ea75a7934bd5ae4b4b6dee2e18d63cad32d26a267d84863dc5a5ade452da4b2ec5348ed52a1aabe0872854f10d979e8f501796239e770ce338ee23ee1ea669da97a242d26cc8c4fd6cd8691a461a815a78823f5cae76157a0b970f7616973f6a325cbe886fbf85056361e1585858585a2e8e9e50a75317c136b262936c2e1dfd569bd545d073b5799480dbc3e64142ab49b47ab8f6e1e198e5997e53ed2165e8bdba44a75c3d25ebc284078018a8fb94005e2580dcf97ae769236f9657d9496f0cd429ca409d76414c7bc7553ed229da556e24f2b873dc6322dd54a39401535498b8241b76672d01e46838e4025110ec6a6c5dadf6e5eabccd0384cba7e2b2122ef3bd145c3ec62c3e422f6778f531eb368f446936042587b9c41509a40c0da3500ff71385db5d039ba7270a39e176366c907bf3c819ca45212f5ccd4e1f8d02ed523931d6410b62c219757474b07a43fe0162fde4b0807e80c2370aee0d9e1694363de7d4346a3ded4ed60fae81a888b1660fd591334cecf490e604b0fff9f4f4e28763744e634dd3784a1165b4c6724e4a31c6b029622dfcbd5814f1a4613cd80eb61395dcd86263d3d3872f676c9e2257736bda651727cfa9bda753538a4e35f625019c37c48c9c8f6deff97007e3c1a2e854335b8c07c3768cdc3e66a4555aab24b53fe6d5decddaa9b456fff9e1c0ee208532bce10e3d68831697afd5df61054edc80614103386871871eb401a892aed57ae9870363c20dae50c30d0c065bb0829002302c680007a05418afc00310aefc9218f470e0968e63347ba28cfe2f77538d020b10e3b1d8cebc020c9bb5e3f296879a8b6d61b1a186b2a7ccc6c8e5986e439abe9766cfccf9912c99f3f3ef1a2f79c59a28ad8ab3875b57c883ce0dd9f53adc3ebf418bdb64b81d724e15b7df3f9eed9f69fb475a26a4a6c9f7519c0dc1eeeece2c11900e41f74ba60d53d7cb01c602a1e0211453d941a3407e9ec8dc6191ccd1a5edadd7461be9624c98f9c0c41a189fc84a228c66f19c75d81581ec61d43086e1f6d92567e22ac6862820ac8b7bfa1af802c6fec8197a20a16ed156b613623c3095ef8b8ac317e6e1900b639510573cacac070b8211a2ac15a860f41508918782b45aa1412c330868b200bdbe02d385ccd70a4c57c1e8c5e36a05a64bfbc48aa52d93a52e1e3923c4c5fbc7f41727d41f2b78caea61d91044dd633fb7efa2421c5747614177f6b0acf83c31738494e8d0a19f9dd962e15999ac1d660218623c4142d7070b92332d4516d0c0861dc8e08a551f139233f2067c8882c40841b0c2aa99053020c316435b8861d5cf72e40c0d2de8400d5bb0c08a553fd39133fc843dd840070f35c8912f39238457d89bbee75bbe57de973e198b92cc3e8159a9e3872cb01fcc3e41addca12d6a9f9856f2b8a67d425ac962b14fac58d92365bafbe7f60b9817184f94d13f18cfedc3bc8081f98b8af3e20f87dc5b27605e5466258041238ce572524c3b91b7c96ee73aef1399bed29233a01c81292a25d25fde276b5a39a15c4e8405daaae52c77615f2c1669308d3478c622f87d976a8a34f82db51469f0592a29d2e0a3ea4aa4c13fd553a4c15fa9a848836faa2c9106bf54b548834faa59a4c157a95ba4c14fa95ca4c1076b1769f047d58b34f8a2da1269f0bfea1269f0bdfa1269f0bbea22d2e0731526d2e06ff545a4c1d7aa28d2e067f58b34f8581d451a7c5ac148833f6b4aa41169f0a17019c272c50d9da4520065ab5863ada7a56915a35044c83a99a65596a653dc360a6d459a47773796f10c22b2ccce20a2539ddd860274bb79f47f9cb88284a2606c230144b4cc6733834603bdfad59865191232c53d2ec6767b0c262ed636247336d9478a4390ba988d6179876b4da873e121bb51f7212b3993f3e9008cefee6d530db58ac5f2bd772c5535a412ea39802c0f55422cb7d1fc3580470fc28501a68f0e01d347f689243c607cf42720307a10f6091836dac802308c095a22e5a93b325d2302d2c7b86a4c6b062d152b401f3497da70c85c623ef52fc58ab03eb6bdc3260c2233cb66c30128488a5ef1336cf658828793cbc762826284ba087e3683c937822d655825e837f32a2a2fabe224c5058341a4552e98bdd11783b1f3e4f261e8c0e08161a467887855700392cb87712456e10d462e3f66089bad3d6a71f9fd84478f257a3ac932171e9b9020be5921424c1722c485c0b81028342569185a8d0e857c42105aab0d751b2d448502082db2f8598d1e44858267c0822ce4ac468751a1d86eaa500c31062be4ac3615944e719294f79c16bb366457548703ecb300ccde75abd8955acab19ad2a88335449d3f1bd13dec072047832c062013b0e9276dec285166bdcd7e35d454439d1292694fb131b3e1bc2f97a6d8d779b062da0b2a4395b01248416f66d47b9669d4def4593ccdcb4c70670d4b2c6f39cbcb39822a4fe67c29e55cca9b7e3675e52995ef993b1007e274fb989becf3d9b1f6ded90eedf4f3629ecd81696fb902be7b0bc84e2df66eee68eb42dfd75ce8bd539b831e3c684321779e66bf0b9155b9029c16485f6a6fbe7bf6a6f40e330ba48138665b1e53c3794fc73e1d2c3980b02110396d183b75bab513889c9f12dc53de9f126d53de715d732add590a67c32734cffb6ceab1cc862abdb272959595c708b56ac5d64ea9312a3526080e604acc934ef1536ea3ebbbe804c8c2559bea89bcaf1cacd46af546832f57fb8a3d58b373f5d35e5019aa8495400a7ad3eb94765a23ada2d38356eb9426c11df52d07a7bda9d562e05d3c83f957c3125cecf1ce5a35eda267a7df6793e06e2ef88a7efbaebdb837bfced177da9b3e76f9e9603976ecddddb1d73d85e4a016f32af8dfab211439a60d5b0e5a207db196d77a1bb25696abd4795f4320b7e52f6a4882db7298eaa2c604c508a5dc09a47174db209cc374595e9bf4555c9db23142314f549a74114eba0816ad862a4d549aa804b58ab3b87c9527b126aab8325475c13e5d30b659c6403d10ba990b05775e25a41a6a55e4517b0dac1cdccc86a8a09ea369432d0451e8e7c6af8928f413575d5785f0156018fa59098122a62109447256a40b81a2061796f0b3221d8a95323c41c98a54325dc81581221176f931505ae521018fdd052cb5be4fc5a5a58054e599111086149d827104464f8d19aa308c748a67c603b03f6d4c6b49d8dc430cc3309557abb0140cb34b602a2f15970a1395ce6686b95edc36c6d5297e404be5d52ad5e97c9526ad5a51096de7ab825ae5bd9b2e916243ad5360e9b4aea8824441979190acce5726cba34925db6bc899c1ce10b704df7e41a17ea6002367daae8b0912d22d3c48d1079d959c372606cae57f2d0061f048197e18dbc288a255d8638462cdbc7c183c2008de98a028834fad0062019c0f9b5c207d718eb84efcce1fe3ee1815bb11732711b7532e8a090a63ead04fe95240da8f71853377be885843251487e0cf3b4b3d43fa3c11b1065b42caf047a26ef3be1c805ecc92b7cc3ca788a6d6a9b6d146cf89613646195ea8b243185f370281a597970b3e36f630c6055b063b78f02011b1263b08620c74bbaa750ad3ba4dca60360482dd8899a73e53f44e472104c5c5c4670adee954144d0059a253dc744ebe7b60a586b4301414d3d2c2d0ebc6b45a15b52003345cd576bf1b1fd692327c6fcbb298969c51096507434d25d429fe0440ed2d2907c1f35550bccf06ec342da57b8f918d5248121edd6685a4328db7639f078251a41d04bd0f897841170674dfdea3b351f688160b6382606e96d9f00461cb8e79331b0ab93434ddecd4864f84a39b699efd706440dcae63ad45a109eaed3c8e5a86c99989e6a7a8fee0eefd18fbc7bc4d69a40c6fb5b100d27f4b4429d3614c907669133b3e2e16da691f26e44c5cc5211e252f1ee2b9fcb095a066d0dc30ba583d3f2d200ecad161f5a8b8e44c773e934ef1ab536c635a9de298d6ac210c564c2b6649cfcc1c7e0c9318207e8c9358c3977bbebb9b093141d8e7e51fc0773766373be3aa45050b3065e8c6af01bdea2cf6300607604c50acf92ebb648f4dccd7c51ec60c21914404a2420aa68d09ea140c1d8905e8dda8853df8dc3026c825477fbe86dc9856506be10a42c859c52ce9d4b42aae4ea9bcba08deee41010c55545cad9ae7ab30e177d798568c4b09d8d75600ce773dc5418b9c158f89a930e9919d97c8b21e591613141324657a2cc19c619f18c6985579758a555c9d6297ebf29768158f98d6e5b30a4a93d6545d25d4aafed09c73ea9863d011dff6e61d1e847e56f15b2226c835d43e5000c20d61e4dc98a08e099a1941c1a20adc81bef36c1871b59e49d94840ab669cd14a933e25359aa59a6a1a5b2da6f85d7b36be1dbf210740a1d10d81dcbe767184b8cc8904095a1567443bf43c5e9776d42565e69c73ce395f53be5a2daec5b5b816d7e2581c8b63712c8ec5b186868686865c43f1e572b95cae1ed7e521f714e3f6f4f4f4f46c3d5bce96b3e56c395b8ef6bafc2de7f57abd5edacbc7c7c7c747f3d174341d4d47d3d1748080808094682610436d99125e03982931614e40bec9865a124a7c7b66c36cc7b5004b85ae84a541a8242c050229168405691ced22adca88b48a8f4169150e16d42aec49ca4fd8411ba29eddb305b02a292713b6654d7e837570d65a9aca3e6092f9e7e8e4e4e4ac469f0d3d0efb80380838ceea38f738368e73c4710e701c238e831dc789cc75e79db0f981001be228e0415aeeea383f56f737083815ba367e9380d327368ef88dcd69d01107f8cd8d53270730e237384e818cc07e83c469136c0bfa9b1ca73fe6a91fa2dc3048cb165b6871851bfac8b2b8f337f4d30659b90ab061b6c51651ee8d024ea1e8b8019ecdd5a334e288037c5e87026a43c9511b89da4d70d406aa6d533b01b511505b680de05736d45608386613f0694319a5553516e7124aab682cce3c8dcae2ccabce974e5a1584c5990fe22a1667de8891c599af79010af004d8f03316677ee608b038f330beb24218e0f10a71ca599cf9916671e6556eb238f349abacc599379d3fa1b40ab438f3f6fc19a5552916679e7ed37e6da89d2ccefc86337ffa112f9c696f0e60c31bc0889a02d0cca860081104761dbc0585a2069088e3e808b32ceec85297a54c6ee078960a594b9f9c2c0d3259ea64b31447a33758075b0aa5f26535802f1e5217bdd8ef5d1b9d7d36340866718eb8f3f2dae81a35de9a1a6f016abc3435de991aaf2a881aaf106d6bbca71a236dc59a793eeb214698e822b6c41a042882003d44c4b84070b21bc487bcf35d0c722e5f1cbe41e60d70e3a783de528f9ce128532a1da67417db2dbd45c657aa005e440db14b840deb0db9d5a35d969ae40713a0862f4835c48e5cfe006a88b12eff354cd1a861ea863da386de1dc247bddf65bceb3e1b015806a700eabc9be89b480075dee8625da68c3b6dbb8c80409306b93e06885a47ce50978e0eebc899b8dab9ccacb8eaf8b3a15ce95a489f5ca64297e9d0658cc8e54c2b4da6f18aea57b5989a8f32f331412f4014c8a5d4858b6193b41568d02d9484547da7182844dd399b20c235b8c51c85e42b009532a14d68167108a64234888221cae0877cc58b4fb9ea7a0252eefc0e815026ad8ab724811e801a2f0000f00880dbe88eaf2b2e3f723fe6a560fc8df96881d03b4f6d0cc2375a009c6300aaf692322daeb10df110fc5789528ea39c8bc9c439823b52e225cce4f2015063a7e64bb6b6a1790e02e7dc86180095eb6955b454f2666d07ba3cb3af5229964ca57322146541897a38961c381677c426b62bcae0388021d79aad4a44cbb149427ab2a1b66243d064391b52213a9483e91c6915732d3943240989cfb93826ad0ae3492778b12ea3c795cbbba637e83c673511cc1b2d90e99d6ad8c43d95563a6ea3516b4201264e9ba56bd74edd6d1bc76d2bdb4a9d3b4aa58df4538d973f9b0c46a41d7f87f94ae5dbf2957fb1bb7db4e18b7fda1f6ba9bf1d1cc771efe67ca986e0b5adf4ad74ad344b36ce93ae808ece7307e76cb9564def3afe74989ad8114b8fa7df60df7ec2bec514bd5631db4413b7f48904df8edaeed3de742fd99bfa392d90793b3b499731dec5a70dad9d2f5cb4b4b4b4b8d02127e60206e62ebe7fa5c2fcab2e0ef357ab602cdbd0c5bb954a5f95ba5cd48f49a7f83ff69b6ad8c435d9fca59fde75db66430e74dbbbeda56f2df7be5913e7e2747a47e9e9f4963a3b757a7f3bb2cfecf4933e29676f7eec361c72a929886b359e7ba5a867d16a47d5d81755209339ecfde9e863d8ac5ce91d67bfd13e9f699fd738ee86f3b88afd35de26b4df943eaf953e5f8a5f0e7a1a6b2844bc5ce9369afb0d7d3c6755bc00528e966c08056749f1bf0df9da5f11a2864b5cd283a8e1cb25357149a794c280213f24e28561814c1cf13831da207cbbed04aaf3359b748a3f815a556dc8b78a663dcc3b983a5f6f00ebeb6df4ca4b367e524e33619ac9a4999e081111d924d8bb96ab6001628f1af61cd8b57758437163cb9985dc8875906ea921bd27b8f113b3f3cb8199de621af28a8fd3ca17d8ea14476b7a48b978fa49354aab048adce4e68c26aed59d62e45aadda9ef1e00b377b04638c3664ad7c596a5643b04eae356fe9f1bb110f030373ad674487b9fc6c602c83f1e78a2a65d2323caf4a8db75d4815171bc069c37830869c05efa222115997f8b86a262dc307ab4b93eabcbd861897e0a35061bbe40ccd22caf0990c973fb5b8ccf40d97dfae495d5106378b0efd69632a1095884e45ea1259976a43caf0e91480c470a96b0692483fdfcd39e7e439bb583957e55a60f874b8e428953ea46b2f5696127d971c362ccd122d95ba4427906b6e31ee1673b797bbb55c98be79776b89df2cd7e201d7e29670ae4e71cfe8a2b60ba8959d4fb68914ea14dfcc4b279d92d4ca48e72b52ca6485c6f99a4d2494da4cfad5ae38390a83285ef05a71a0ab3b50a441a1c6b1e000462dfc00cae51bd2701bba7c8e6ed0c20f9c5c3e65c25cb8cdedbadc6a451933b6b82539a016eb4a778baee1805bc526d3b31a6b8c37e6ea365aabf25257e9519e5c36faa45521b7b68dba5ead0285e8101fcbc18814a14d28d096cd162fe1d001374b45195c04523137cb6cbf44964812da4d5a35ad7c758a97748a2777e638eea17c71077a8c1cb75d7bb7bd6413f9a2f4258128339fdf4d5a0573fe0b75fe7cb58a7e9658e27ffe6ec4bb387f36e18a6db989ba6a85a9e1bc2d357cc2e7faa0b92e396e44cdd7e5bba83e682ee7cabe524324ee8a4639d37168739ee66e73ce89c49cf3733bc671a5582a954aa8dad5a99d3b0e8d9be190ea82839b1cc7451c347ec695cf03472dcde423b978f795bf1ee6f417b75ccc7694cee1e02d620d696ea491461a2375c9ec0d6dc8a553d3b4a99d1e071d72b57fdce919077a75e5ddcae33c574d371d891dd3ba6c9fa592a681200af5a7529c75d9ec0d171cd8768de3321724384ecbe6b90adc52a6d99029a790e3ece9d4de9c9ed99bea8326e4ac0f9a7bb2b3537facff6e6b382f4cb5b15387f90b3b3b0563df72fe94e8a25db98dee668d2bf4915b7967c327eeca5b56be125dac58176f71711bddaf56b9b021e92db65d9dea576426b65fa45f7bc73938d2b11a2271b14e35aa45a76ebeeb865c17d3ca716c43aee99da9e2e86e3a7f39ba9b90e06bba89a3b9f13f5a0b74a15e078a41df8e8de65bc0e9a69b4c26d371cc9bac357d88a962a795a94bcea04e5f0e634314cb5d5897b7c496192f3356ee5263cbb458961a5b66c5a26a6c99d24fb5547ae9a23a5ba6f4f8e170c9b1dd741c9bc9deedf438361ab78ee937ba598f1e07e9df69245d23598dab9186dab95a22e24e2266cc881123958a8979b9f1e5ceafacd81065aaa8b074e349144fa6afd4d829930d41d14d8f6dc3d2bf6332980d65a98648f8a009c237d3e15dd3865cca715cc5b16d1cc7711cc77143289db52b718703cbc15bdcecb4741c998d432e12d96966a31577527a1c54db482176956f2e38bcc59d77c9517a761ca5d28754171c5929fb7441e20eb9f1bb31add729ee99f572c4cfe388438edcf812fdf721d74673351cb273a30dbf63d6078dc69744ba0d49aade556a08c5eb7e4fa92112f77bbbe208acf366a38c669524085f8f6b758acfb9eeb41cab53ec4406c9976c1229f778f9a22fce4a20ca245aea924ee413eadabc2b5fb28964fec2e54b28b126ca57a4b375394606026269e1520bc653174faec5b938d636d4aa6e821322413187bce8211b14dc60bf84ba1823afdd00a4ef39a72c79e04d197129ead298e86a31683492a673b5e438e8522ad26a17c102d87155b2934e69cd928fb44a6b56e85dce3250944119a8870bdb87878b356c885a44d55cc20d5e60854b1f5540e93f22805cf79cce9f8d8f7a3947745305353a05cdf33c1b789ef735010cf9e77a9e876198cb054670b58a855fade24e7d7a6e713cdf615de5ae2234f442c2b08e6d088e4eb2e1ebed6a8ba6945749917bb8f2e044c1951f757572d18b5dc4581e237f362c54deb3a126874e58d7f576e7c021a1200cc338b0267cf74d01729ce6894014f8ca81dc47dabcf1c371e2a216bb58135e3291db3cf29d166423f23c51e7897a34256ed034cdf3de75e70721d0f33caf0af26016577eb4852b2ff2b8aeebbacfa6fb79b95ade48241269224de3388e25863baaf16a11d4a6d73cacee61bd61a657525cfa39bb8f482a295140be22f0291c7790fb88c330add545cf3bfd6c3cce3e4ce3793b1b414dd3dadbc01f292841088bbea8eb38ee2038ea241064112e1f944ab8fc91a4e2f245222e62f1f30139f0659524c5862f973bc781a27b959b12ab5c0d5f6ec9eb948742691ae778f7c091a886e039a755238d7b9771f3fa78b9a3dbe814d08e348fe31e5b753ac771f75a453a7754abba7336f4f172b1733d5780d8916cc7ecf66dae687c02788535f07052097849dee92df1ebaccbcbe365d1f87a1e77ca5dd4759a0a97c2811ce91de9f2524af9ce9ba44822919e7d362454d7c2f72d2211e744198e7b0af791e823a99cde9d409144c1e5bbe0f2536ca8d1e0b2d4c1e58fbed3e9343a9d3496faf252519aedde9d7e369de7755c45a134cdfb0e845ecee37a344d13d529850aaab8710b375a2105a2e97158e0d1620d34768106b7f948d785bf1e135186e3b883439d8a27bf006a1a4602c1775a5cfe1b2e7f5487cb07f720bf1b36d4b4cf729fcdd73c5213c2c2207c4597e3380e480a71b8180fa75d54b322805e7dcc398ef37971f1f8d97c31009510550c1453f414d3dead81814c2fbdb376ebb86ee48dec8dbe23beb78db87ac948e4b998d04eebb6185c02909033dee313f01901ec1bd25099cd737f3c446febc2a34f4ffb4356e0e82425d264facb914ec52cfb4b96bd7838ffff549a2d2913cfef5e8f7a41bda07e1b0651f252ebb141d3a9f897aab1aa00595763a17a5a15928e901eaf49d12a954714f8d8b7f4d24f3fe9c81998c7ef2425a41f987aca91323fa39fad7ba5f0474d181b058dac18fdac008d8446504651464be2472e39d3ab786cb26b3289975a1fc070f4735b37aea8cc4e3b9d3251ebe95cfe86bb289d8ab61bb21e914e4539f92426724e79125015f12425a41fd2eb493ca92527cb2d7a45a28c518bbb281e112f0763a9f1b244f172ac7c27d4a968493fdd10a98a2e4a17e111e922508fb14689878847ddd3691533b9f1deb6bdc435484ae210f1f1a41e39436d8f9e39bb91154cc839e7e7f9e511244d1bbe1c7bf75299e811b1efb3c1bc1e928951ab53f1a39f1e1568d569e571b6521edf09c94f822ef653d2624df1b2c4d556c32eca8d47d5d08bc18d2b9dd08da41a6f0a483a4224fe742c4535875b917ed2008624255de3aa8ba0ec3e3e4909a90a5210090ac98a16931b493f37925e3746d2931bbf8d35d65cc24d794955b44c2429e954ec8494c44ea8a36cd11482d2aa108a2b3dacb26c8e730a6db655505ac5766445a75ada513f1cfddc788df5d28eb4ea1ec8497243548ff8bab16d9230be484a5c7448695db247faa94592921649094949fbb8800c24252d42370231646a29164022351446231663cc98299d33ca6923dde8563150af9c73ce69436a33fa3895f8bdd1ea9d912fa3a47fe8a20aec5949296587daedc321c3a43ccd2676c9d4b28c5152f98a9199cfc086c80f8832fcf5008c8fe1bc91871d32b979d0d376e1ef3c68c369b5df5ff99e7dac69633de5516c410de40e9433bca12413013233b3fc8400cee04b6a8427638d84a256492610be6d9b095d8c09695852b6cb19a6419491d7410a0857f24e4cea1b02d80f7ffd80870e38893f4028178a083006122f57a5ba892939b7a8f2805014ba4442ca4b32dc44153789297979140a0451a8a955500ab24954912136312fb529292bd9998f818a015da89dcf45c76d8be489ecfd2924c9b42176fa41a09f615c43a9758a1988c341968d62c4300ccbe4a96566ce58e3acdfd072b6d6ddddddddddadc5905e8cee191b73cc347546eaeb49c5a091f5f2fb47d16c96b20defa89fe1a3d68bd9181b0376aaaf3596643676ee44b419b1743999989271e5bb65ae7cd7300231b10879ad3e16219f7563b2a7d491ddbe4bca9943a91514a3d4c5f417dfee32ef3ddb806817a6c5c5edb1b0e3e49a6ec4c2ce92cb4b3ac5374af98a35f112119d56b0894d2cd060e7c62b9828b92175616107caa5ae5853bac6d73221ad664171c58587445d749115e2c2437496b35821a20f59a1ac1056c10e1b76562e10403d75943dc1cb539cd08704e44022f1c74547fc7cb42ea57819a854358f812c11fe51c2a5ed93853b2fc28062ce102e3d8beccb51b66b19bbc9e5c9b538d7acdc9278d94c1e6acd35de5247bef3d559cc349821ceb46b0d97ff1101a459c4199787548b37b89ce5a1867261a12e3923c9106558064d269d9ae05f6a36246522c785de6df9ac3e50334ed14262c59537b690f85c98961795d4ab08d2d2f7c5ef864422ba8d465596cab21271e006ce81248eed78498973ffe9d3265185ac8057d41569f09338aa0ae1156a7522495c340d04b925daea7c7d430051dbb67d6bc596ede60c512f75018f1f031670944be5d5022a5f242e5f407d59692e5c8b5bc2021249623a0bbe5ac089f09d19adee0b7c1065dc17188943c48b7abcf1dfe89a2ab780cab9ba087ef71dd9669323e08d13a853f32504903b7777ea8a35f17c8ed3c55f912ce027d35d30e0e52c77a9a258e9566f883ae9892aaf5c5658aaf45c2aaf5e56564438b2c7fa595ffcab94c90a7d61a9ab53f537a0e8b599f40bf5b05ddad550425017bdcbb2cf265ac6918a325e9fcd2bd6745f5ed2331cab65f85c8ff5bc69b912c7f9405d8eab2040dd696f5a0ee362010c78e204499c05bc4ac2ba802829c347c51db6e452c27247d528291291d5f96a0136b68c0babd51075a36db90dd952edbbfa832f072a91b9811ae32dd5decb807ca06eb4997cf123b752390baf1d0ac447c882185c60b8b3c54b5af503887663cb63ba5299ba3a9ad5529d3135afc51a5daed6922f08a08b02c9381714376e71e6635bdc908643726e380f242b697d3f8368373b906ce5acd3a9221ddf489d5c8e35abe04ae5a6f3ce13b146133c043fc62df010e5608138a3955e815833f3f8124d9ce15ab1155d9a4f8c2b6bcc6f8fd7a217552daa2eebc0ca3a4000b31769826b2c1187d091335a7435b7341f39b3e5581ba240d0aefce80b44bb2e2a7721eaf6519d6fa9aa7715c6b715c4990e43ac34be55027cd61a57d5021c46ad3956f97618e20c0d430ce25b15e2b38efe718f60c45a3a8e85b5b460ad168ed52abe04a89246016aea28a6e66bd03044529499df40ba0d6d515a95fa49a97bfa811aee497b695ae7c899cd75140a0435ad3ba2723f40ddac8d1b51a7bd37406d39006af7ada7a7673bd85a4cc554bc8d1a634b8df1d6788e43c47343600c89e82d751b926cd0e470e3f170e387ba3ad3e4c6732ca66999f818a85694ae685d74702190ec72477cab07f8ac46bca51ae05d05c0e3a783b3489e405df4d843742149a20db9d38f07ca0395b3a1076efcac92e6a21a4dd72af752ddeea24e964a6b16d429f0fa40ddd8a950bb1abdacd3aa2207bd0bce56950e82e758839b39daed34796986655186e90710ed728f1a7d357d7d3f00b7bea986d40c2175124edb2f7a532a65425d204bd6598b90b07c0502bc6291332c67d40cd7922e9f36b41f0bacef445eac94097d7511ddc83bd596af54178fbdea523c937c4d1893d6e2229a36144ac890150b50ef95abc4e7d6e97b37c3bed1b704e59e0c71087ea9d25794d164a552a01aa30cd2f9a3ae1f80a2d787d40524bbf11892170888fe629f70b9c80a61390b503609ce11973b14ab9bf8232e4b15c22b9658919c60054356a2cf8a04654b20b242782584054fa07ec46ac84af41b48508f16c9099e60f913abf82d217a09445648af585c4eaa213543564bb7352cc13c8c5bdcf927620d261287e0cfe8c2c73c3d8c69b8f316883592600f4455fc3c07a20a009f6722aa02f0f90ac49a184b519bd18ab8124d46449aa872d151ff57eb12f3788178bcf3a53893edc419d4e7c1a8fab20b633997e55a3e00e30db996b6ca94c81917fb44ea2ce0d5cbcbf9d98f9cd156fc1ebe0b1b6d125c8389643b4bd49ce212d48a0d519bcd4a966b5ab252feeb01673fae819d691ad67099bae1721f2e9fdee1328dc3438a86cb6231cbb52cb5dd2ad916ab444b764e6ee3b86cbe66f6396789ce796d6a76ce8e9b976ed8b98dbbe23256ba41cf51fae1a0e7ec972308df39815ac51ddb8e494e4a2e13c0376da9f459aa20f02eb5377365d61215747ea800e5c61f254d6e485d3f5478c3a5515a2575a40c5fd36cb0d325b2cb1ebeb8731467da15760d8ec5435419552b9fcfa26a53993ebbcbe639570b2dd18e72c755cec5b5384ef4eef40b1c8b8221d231446a86a832710d8ee5a282308ff104f36ef3326e49cb85a5542bd91074519a9d2abd44e7f9736167a9f417c772f1b0e74db5ab594ccdaf54195333cacc79177626c9e85b6c5767a742efd20be0b30ae03035a469b87cd1a976c2bef85d00efb8cf0603e78d6f6ef3fbf6e1f8222863bad4976c586fe92b35f4eecafcca0a77fa8489145774f9b47f7ea0d0fd5481881338d7118da37135fb272727278ad58c190fc1199fff4ab70389b07c4915401788bc38d9756286a8cf46fb766077326d4db3326eb0134ecc6bb40e71aec64bd9075ca20a37deb0390e96b3c3c98407133684d12d5290f50ab4375838584ba13ce1e4c0d1e12474aac3c9d2277c0728269b074c0f98dd03e5038de2873f58da24a7519059fa524113b1cd826ec11c620d67a910f721d6504b815a27d64cbb057b85c5c2ce25930bb30bb1667a81ba6816f40b940303c7840b03a789411b83f6d2323264653043acc99ac49a202a678835413834c49a207dd3106b7e00c1ee769c236e9052104f8b5813645e35c49a1f38a31b64650db12688c849ac09825d53acf901a4afe938f20641b521d60401dd703a9f8362cde95d010a4c40023d22008107f038ff54a9ab52da24ab14c8491015b21a7806ee0026de8063e00cf805aee316381fe73a91721bf438938273e2d02b00873e070e3d1238f43870e86fd4380ebd8d018e439f001c7a048007380efdea88e3d0dfab1c073c8e771c7b9cd3714cc7d98e931dc709276c7ea80401821e28e459ef893dd9a093e9e4c4b49980b64ca549a68d5edc358efb0d0e7d90951b840d83808243df4cae802a796414724716913a9288cc195a5569e4d68e4245145418a1e2881453b44cbcfd84a16c4aa264445a265e8d8a222d132f4729a594524a6f6cc41f2aaab847d43e409546d41eaa324712a9524716913b320ac91384102315d3c97a208dcf9fb73ffbb547f973e7357456e39a01cebd963471013171f20a6af20448c809942039c43d6915ceb4372976e65c19a5536c0007701289442239d1c7b9c91eaf137c5bc5a5018e4906b4264c989c60803eb900783e8562014ba3546094430121884c20081d09c028d243b5138199282040c3f3003e668407c66a150e5f7a07589c196a0db09e0dc133c0e2cc7baf41ed12d609be3837d8e3ad711dd607cc1e5f53b102548ca66251cc546c072b82e96044b01c1a850e550aa5525ba913da843239d5ad6615a7003f9db500ef4486dd09537693bdc92c4e7621ee8435ddda1b93a9491040294e6004a93c5109b5ca09ef38db9db0f7ec8db5385b6c01a5554ed8e36c338fd789edd6de6c1627fbf66c8b2da27cc6099ab30f88939d1eef7ccd289de2abea8451e7933a9d0851671395946aaa356a8e33731cd571601c2788e308719cd171544e77c2e6474dcdcc8cea372de4a382f19b7e22058c207ed3413d4108f19b76724488d16f1a883552f94d3731a292f29b7ef19c9e72aae2f49b76ed9c6a1aca14cd248a4eedb8c6d1b9c3063338bb88866e74a3db39ced09dc744557fdbb62d7b7f4a64db90bb23779cdccc86dacdde5d0f4b98c2b16de80e8d0289f7af0aa0c88633ba6bdf9132d8314de391475a0603674856a7b02ce585ee84728746417962cd764c07177b5793e0cb69fde9c8ecbcd62919651a6361985c290217e122dd288233623038236a73c4fd3262ce264da61136a0a534a01665f39ca2d82999862eaa26c5b00f73d1d1f1d82100f2e5cff0067bbfabd462cd6c143001e335aec1e1908b75db70de207ca975c901f29bdfdcbb2fe22980618c3bb528e3b361216d23f61e4dbe27d6c47b9652726663744ada24da4a569499efd97ca412eefd1bee5cada2535380dbd989ce9ddd40b49bf25074e6d1c1bd8f7d3a9eb8a2770dfb8aded51ff2da6905c237e6f63bad867c4d3b4bd3be1df5f251536586bf1a886a969499dac491f724ade81bf29e6cb326ca9efe5501a21e4ad60f3e10ed9abe4252e98eaaa7fa3d01c4ce3706a13ed9a753f3f3dda972159d9a474d94e5293a35c1af9886684d54fce5a74849b7cb90a9f8c1ccc2c000b2fc8c2c99373faa2c45a7b86bdf43eeccc3dd1ac1b28f328e87cf6a55db39597502a0888d886cd60f254b8a58a37d4e99e4ceae37f240ea0d9f7bc7d9907be7bdf3fbd51fdc3c1dc5bffaa3b56035cc4fd903073b301f588b2863f61ee67b5e4e1a28e9a12863a7877622913b27f765cb40cd51f070154cc5140c0424817cb889cf122b7c58ad0a19887f580cc442204fc140df1740971bd2bb64c919cf6a1a08a25097ac66e904f593f91e9a5f1660d8addbd32db9811244c9f92f0ae0bbd5aa5ed2aae8ead8d122f1eea4673c5ba419681e0a2b824e3ad571cb239d9a6d27fbdc39055771e73b4aab42f9a158d37dbef7106bf8939f65cccc0f42eb0f96528a3ba9640121d6048167da087209774a28d8e81e9233ac8428334f85ccb953eadcb905b973e73f2a40edf4fc1f3c8fcd4ecd7335895abf2780f3717eb2b4e24ee68dd5aa23adea9e2777bedf7067cf233db7188f41bd80a57976223f53311e837a014bcc32d22abe9341467931b2d099bd35ee99d8a74519f3dd6dfb3394e84b6ec9926a9a0d8dc82c2663ab2f3d2878882665dcd09faa50be1f6a9f176be8e3bb3967cf79293fa4996fd09d310880f4fc89493aa39c2e305e7996fdd3dda18acb6f296ebcfd6ed4e7cf861f836de871530cbb397dc7765a1cbef241f84a7bc3efb78dd129a125773a316256c29b233a83f06d1b43320719b9508adcec1ce5f2e9132c84aab83037622164048b3b18b935376261879c8b9df23bf9edf4dc67b39ddbe846bdfb01a11b7711f7ddcc03e18b3d661f851f53eeb6cafdf3fe7136d6982baad7c06f7fb94050973b9079450fe9bf771d2743e47dab29ffa8cab71a4fabf7aec6dcf8ed8071bd90afbdfb6ef049e7be1bcce190ab92f223c8b421fdc61bdb186b7058e8629f12f4f40e4d2ecfecf431be65db1e661bf77d39987e5700b3475abf1b3162e480112346a7e2e9b11fdb3f1b0eb9a14874fad97cef445f147df7de7d5700f9c60fc8bcddbdfad97f95ded8c5dc185146a4e71dd8b38a7dbe06e10f01d9fb01900e2510696fb0cbcf0ba46fc8e3c82dbab99160d8a4f42894a6d9f99e97f57677fba897add666c89a5966523eccb28cc687d96796d93134d86998a6652c7f66b45c4d342c468bf44e0b46190cc61ac9524a2250cea800b347ce3ce62e9eb9a226e5b3456519565fba8ef2bb2b4acba29479ab98b30ceb97d317f685eb3bed19570104df2aae9575bc748ada5b54a728eacccccca176692a460f0e1011ad98716993b063b055f40a5c00c2a57f69556c8364d4a51b9077d7817d768ac6b34498350520dc2ec5a5a48b16af9765a90c4b5d796932b6c21557b3299a8a42937a5210026f9040115df25d77f9e844d6d518375b39068d9f0ef9ce082eb24ad27545e68db93287049de2c73adcf830bee1c61e910c42846820f8bdbbfcd5f9ea124938e95429cb6c96d9d68932b8c60f20f4d272cfa7a3b3f2f2d3f144f7637bf7af02e1fb75e7b7a85cd1eaba8ef5eda8b71b95d22d29d3e79e4ef9f445dde513d97a71b3872f50dd4ab1dd32d956c7ab442dd44242a6f30de5ce8d42f2b48a3b28c5729389a36b10ed6e5d35559577f547773f4a4888632a258cb9f27d257879f995aec25a84f3e796deb18f041fcacb296ef6ee8a365871bbcb779bd7a3021d4daba29c51693e2a80dd2711349e8f38d31a143046215281382359af978d38c32f29805823e5f233a24ae5f2444415e9f234d188a8325dde0f975fe30c09e4182e3f74d1baf2a238235b57dc6ef1109af77d530043177981b821778fad446733235a8533e4de90278833302cc367981b6a2ab86c52852f577ab126aabecbcba81a5dfe8b339eb43c2238baadeee1e8660f4721fb883272632228eccbd1bf9156b65ad3be1b7dbb734fe6f3cf4a416f590a6ad9470ae0ecee9f14406ec5254c42e9926190f5e63b101e7dbba9de64d9b78f44952fcdb22c1305e1fadb81f50757be5da453b7c1cc94811f3deb40259914a6be2625addaaaf8d9f8b5c9548a46ca98ce46dae317b95da479406ed23a5dc82f254b24f1a40ab9d3f2695528772e9faf7842e4be641471c94e93195e314b96ac022cc9564b0a7d5100bfb05bb78332d4854d832ed23a2d8318c41a11112ed83eb81c811a078d049f9e4256eee1269dea580a69bbc867d33b9d92b6a5b0d18102c83dad5ad2924758b1a6cf97408835ddf9bb3cabe28cba67ff6aef90efba4e7e417e3b53fdc1db8fbe61ebb8a05fc033b206977b071d041cf9879c5bba8d962c3923b3903d231b4a9f2ba9005ba6c474caf4eea38792c5f753027e4f00e5e30dbb2545f7cee2c85b6ab56a899357c85adc982b2d3749c5e899544ccf6554a95568e0991e5f8b8eca033887cb21b721e521ff41258c71437eb1143d03f660bcd33a5a4a8c4e991e4ad6e58b2e59ad3a227bb8464fc1437cb577a2e8148fb69bea123509216ec8426cdbc6dbe8fc2e126b44e79340ce488e43a617c9865ac986208a6ba83c4c5d2fa8542edcef2c150bf73baa7e3fd5ef2b32ee77af7ede39c5b64edf4d36449deaf795fad97088cfbba6a2d1492024d6a468f83db2140a15230d0a9581f12736b9a9ce548d8829f952a5892979522522ce8829f9942a8038840c1965c88bea1765c86b72461465e483b8528359b945ae7c9c71a3a6847c67b3877cbbcf09e0e8373837b153236be34f27e353be1e51467caa55143b7dab281660b85d7adee2f6c801e3c64e854b74b27ef7ea0a1820eb67bf1d99d6221ef7bb09222f1213685505de850c5979ef1a0e91d5ab2bc8c213e4dceefc35c0b3b2afd5b89a29f841afa65dcccacf1a7363d71873c89661479c817d2e86bd318b5dceb818633362a462fee25d4df68835f156a053d8bf1f30d4ee4e50185fad9a475a45df4ce9775ad5679e1b31f8f840acc18387c08edd03b1467bc83a60d0c5301ac9238c64b8fc211716cd70f96114c3c59af4d0628dbcec3385953212c421c19dd4093132c7711cc7711cc76d4c5973ca39e79c73ce3977368d1b6a1ec5982e462923b94ca8555088d4a9d3a9cee954730f670e36ef69db33ad53edc52e62be4117a60539936951c2128be1c6975813fba34cd3a96ed9337ec8b0a3878ebeeb1aa27a8bf1daf92839c3cc1365709f52cde7529af5e4000cb59e4bdf498c6ab45571490c407006147a41cdb0e2312efde4fe6cfa2de71e6abda273e916214c4a1f59057a30d145c46f5180e1e8277bfcc88a518b85b04a97f19372ce597a27bdac96d870317bc38f5748d4c30ed880a3e56e45c090a48401db9c53de90ceb77424f47f7979f6a14cef640dfb621b909dcf4e022041f7e573c7673a9fc4d7840a4ba110d6674b437cbcd4305372c3d27d48a04b3a5720ce9f8d9557f6b0613e673a4b473d3655be4cb46ae591e526694395bfb844ddc5a50dff17f3853fe7b1cfe6d8ecbc3cf652c3eda52b00b500952b80f8cb33eb827de7672ed3e69042584258576e8fc96c34bf48202032ee3c5176722f7d7e3a48e7abc4f02753c7524328ae89599aae239c97d83bcefb4cf3bc7926794d9f980d4f2669b22b3ff5e894a9aefc453dadacd85032d1030ea0e9372a701bdd65efb8fbb6c957ab509797d2be587e7ac752657fe7fac252e5f9fb5eacdc813acf3df13dc9af48b90365816cd66db3464c3e7e32bbfc909055ae00e73cd7f0e531df2a7f395a07e9b29b1e56b330bb134342ae182b0766e3cb61fcab211437e3b961e92fd6877ce9365a76a4bfa8f3c2a8210994dcd2636a2884754bef2167e6ca048465100824e2b51689e8f11305e11ca64ba2b6029817bf92edb103862425337e346a7511f11f11301cfd905cdc7553bee32aa594b2e3ae931ed334dc6cd4f19b8009c542b2a2d29b4c27138ac56482e9863aa14e68729df478ce01b482a464f4230330d458a41f528bb46476429dd0e8675ab181442663018277bb2425d85ff8be7c569e48746a368046cea43c46f0529a144b922d56ce50cbe43302386df44be53b475a60f9637ea4f904748abb2e012e1368798b15c23b88e2041b2d71009e784eacd39156bd3cfed4d32ad3a350ac7909ad6855d7201d8943c48b6eb7d5d1e5684777930188bab607f0abdeeda4f7524955982ae9a78a6ed73c656c2afaeecf8c2e9fd52349310390e443ea4902ce164aced096c7a7220a3ce5c41aec91d505451971cef91972a6e5f3d88fb489d30e209fbbbaacba3907301cfd6095479f5a21fd4e7e38fa620cd856a39f3e80de16205fce9694993e5206abf3355b3da44c94020c6978b64855f831495ce50c4ca9547ac1bd78f1a2c62bfa4a2e3ee2381084a9a71d29d38561d3b8edd58473f151ad5aaf9da8a4ec14b651cf3a44340200004002f313002030140c0785a2e1703ca009935a3b14000d97a85480521aa6399062ca18620c1000000000000000000404002c67845a7c68e91ddf2be554e9630ceecdf56e3f953178d8662103c2459293e263687db3fd50b4384b0c3e486a5ff73c1b5d68b3cb919b562d4cbb9b2c1782ee4f1da15affb6755808deb0b438397496516326fd44cd3105dee1f1722fd23b7673616a40f1b5da83ed2fafd602374004e3fdf1d4b9589492da877eb038d988c31efefe26c451bc14098096cc70ce2af97d81f541686cda7ebab2aa467eacc0e905f9f95fe313d528fa04ad370c2c8891bcda1f639db6975bf94f558f7735bada93e495ee6845b4cb36e9ebd1091084593779a780217aabb706c86dc0ddc9a63cf1e993d04979786c5ac7bf7bc3d65bf7d2a6b7b71a3ff189e4875723d850c797732a3d62f77a284f9b0fa632b21434658b7ebeb3c191934bec84f0ebf576071fa434f868e80c4a8dc02e68ed494432f8f6154a3ad64efeca931c4de88729af6a9a8db6606f3a7f0e1ec429d32abcac09d1ec0cefd449fdafe3e4290f874cd511e9e783d515ffd98785351c32b8efc20f0c3627891a1d3c972a9241e422e235433b761d0b52b74402608b0ce4cbd37918530b9276f8565f00a248906adf116c291051d392b47b1e081e0f3eecc45c9ee0582219584fe5b4f1e7ea81b021c79c8e8b18da978efd1b51cccdedc1e4b339c79ac176225f636489271c8d92544bce28de5eae13ec267fdf9f5758cd305e73f44d940be5d26502a068123bd221085a64cc786b990ae64389a7e00d2c726582490102618453450b8cf55fdc88b0bb5239746ecca7f3f0944a488f24045a2b19acbec0048e5b2586a2662c065effa36ade309ec6a69a3a53b253cf9a7a9bef4c4180ccf3a1f8aa7ca5874bec171ca394a1b3a8e7a4d638e45dafc0daa35037b86063aa06b1aa57bd763b11ae4f69280fcef007ab46e19e5eaf598e749b4dce6f055faefec1563e0d8b017fb56a7af9581ba9063fe77e7c5176f5bc1d00c4d7770b2aa08dfce2a91909c4580e96d957b1ae287b62f6d01a5e7b2c4f8f00d7b687dd735e0362b6bf77caf6e2e3c665059e6c9eb7ff5dda6598262f5a722501e31e6af0f27f97a11a35ef6500a0cc7f648f13049841a42a088c8b51185a589fc8256b05de7e1fe5861d2bf608cf517718c9a86b787c256714a5668ffea229b8e68b7829a7344aab08e1614cf99d294b43e177d679602103e786b0c40aa579ef329acbe50ead1f24b7487493a61407da6034be12b0e3b854c66edf242f73bcd1026b20ca19d7444c7b88eb2ff61d68c5c4fff6823b9e337214b0144eb0c3d80819413b2ad06044de19a5701e98a4b6fbff7d54065643cb8dff9c31b644b5669bc2824813caddc942cb87f888ec3a53551ac88adebd5d7b9db4fb3a63ef9ef66247fadc141062f0cd158c6f51705fc254f45cd4139442a44757893d15b8e866b04641b480c036c40bbd4b341cbe85fd0ad67c1f7e75434fa89d98288fc272c08c9fff8cb36ef960c4800785d2a094e1b55582d6823b177ec52a3f16f4ef059f8630f8b7ac54489619f7bc67218d9b1ad25cb80e6f6b360eb905822f58423f212dd1f16f0ef555d9d72483e953bec283c5db4ab493d862468499b3a25ed39688b291cd44dea07a4e2052aedfcbcbd4999363a71cddc0b2454bc1ca52202e68a15284373df6b371035c8d740fe6d0c345d8b455c6fc8928bda7d00752d881f86d5fa8a92c9c128e39015cf72fe56a5edecf012fb642df6f3e98ea9383ac952076e8fc9430a105d070c181de321273831a1f3b707effb65a669f19b322317b6e1af99e8316c50f64591b89476e6f2b6c6fe52290e68c5949e59a88f7d0ab70125a706b16295f7ba1f1ca6d55a42a3403cd03367050dbd03f4d4a99966ccbf65bb66bd5bb5bf8fdca39178af6c2d22622cfe030f510ed4499e7c8bdb26f4bbcbcd605d0204b59dc2d5c471d10b33cd7aa5a5ff3105284ec2061a3ebc3930f4b03c6b450a19bc67410f7dec2c59275b564d0da166dba3e2a7f76e497527a848c3846164efeed04868bbe24e351560f39620ae63059136b5fe7af9a0d983f306a890a6bb3f0a545c1830375f4f0ae4e3f650e28a6eda0ec6eab4d0054e57f529aac04dab4b68498b47f7bb8f71994b03b1f6f2b87edcc3fc63e7cfc7d1ed6d8c1bf2356598f462947852d3b22604d867cfcb80b2ac0520c45ba39208e1b53d4962a5c7696739ca5073d202d97e4edf94da60ddfbc50468de5c0b8f0b08d45bce2bf1f6ae4c8634cefc4489763751b5c442534f4a265ce5063b6755f1a47025ce8e1731e8b5d861ed4bc4992f4393e02d7b74727e4e75110d6ccca9e4c94b595ad23ba036c8ee8871f62ba894e74ffdadece724ea3db0b400f57ecbbb0ee15374936eefb783bcdd4b6878384b79e77e7a1fa8cc0d6ad52d9c79331c32542a50bacb275c25cd6d5b0150e60c27ee5aa9956001decdf5b45467a6c1e26dfb508e9cf2c8e02e156694555b19d2e441e4ebc9e5c1c9bc80d418c070020bdcc9fcde7a2d5d9318250651c1ab53a7f3da51a2a2bb0c45bd2cc86deec3c65376c19b0e6a6057c3f46deeeb3d3300fc6d707a9406f64e2867435a3df51361f1916ce2ecd4100873c2e1e1a03996307209a322aeee9747685b24f7eef74c219777847c53c0cf966f10b3111ae35a409def734c82df78dc2e26fbb9df4bf4193b04fad988ec3f95e13c3b66940e4920badd10d6544d66823a88cc4181c0e3589d097bf196d2cebd6fbe917468e91a7410ec3c746a7cea3a16aad364eaedcd25f842ec5a2a0208cbd5d3918f3d01ecd22087b987d33f0c7ecf9eba893e798ed0e45b65c32b976920181fe801ef0c7d3de5ad69a6d0dae792620f71b952ecf8bcdf9b24a8a36e26139960ea53a66cafbcf6e23f1ef03298896e41485dd1452860395b7977af282605f779ffe4aaafb52325f54677ef215313213f95e2c72ca0b5362a84128f433bb22cd9786a126c438eae3591e7bc2a877be94a3634dec862814769a0ce71ba7bd83598b93164645d9d59f0ba3c59d63df45c8a5c9dbd308505c3e6204c117c5fd9e5946015441089e33198d270287c8c7a8c4a2dff8a587424ae7a03a59723abf74150fc2720c84973e89719820543196d65171e396e7e899a21136c0771ff945c946dcdcf576dfbb6db49165748e67101ccb5626ec23edb11e21fe4e2e7041cf8575b18f3b0906e5ebad8d16349adf85cc04ac01016a3a32721a280969d81395d9bd1f2d340dc795b4ee2102ff8ab013eacca3500c5551e189277cc4685a49f31fc0d9d632523313bc208b6d654a2b1d72c385feec14541179137aefe59ee6d62641f99d3572e4d223fc8dcd6366723e7411fe2a2d6f130e6376851843bd8442662e3cea843b9e280a35b35de79684977c16d739564c746968402995742bc6bceb00f24fef9c95bc8babbdf68b593778919d191684c4a90c83b0a192a4ea45b08ca53982259404d76584ebad407d75f03e9c07921188226d252689d1dbdee49bd1a16eff02ebd922d0361f9e9cdaf7c9c3f81bf69ba79a5fdca3f6e9792c2ba7a7a38fd6e66d8c44d5c0f017ec56055c32a19b5805572c5cd283bfd8a8b091a7164598a32fd03925a932b056861b495bd1e151398f4f4a6f7f358d2203445541b68f17e6aef3506cce7d5f7eff1459b0bfde638e007d45f985372073e78e25e3ccc380eda93705caef9d8051f36a66bc33766ec4580b609395774d18cc1cfa673c4c9bca262a1cff5f501a034267441ff13a9e8a2bd3753224d7865f5c1f7174f78dc742210e3a7b7e17efe611200e91d57ea17d8ff97b3a4b5569ba1f61ad6cdf9b8395deb85c4caf15b89a63b51407e39023b05cc90569e96c53ecb5c4e3e5285dbb3070e40b5706cfdcd5ee4cc4802bb7bddf2d126981ba0b66aa59426f4f1df681d6c0c08b9845666fae685e5b92310a3048fd2e5ac409956b95d99d33dc8ea8881fea8a673a646bbe9dc3e1887992e657f47d1b7c2acdcd38d6a664ed4f450534d860136c503c264fb3c52d25017c88dc2705001238443baa2374a07698ecbd35d3604beb132818f436f136b66756a24ad28319c2676379f96281e2fa9412c755b5a0c3f07f057ec5b82c60ac6112fa51d0f9779506146d71a0064130788ddd16d8d37d36aa2d63911bbfe3dab6f75b3b8417b1e1eb2467610bfa651cb34eb777c29fa8f11de2e57ad1a88eafd892e6e55d2c09bbd0979f3a76250ddfbe99b724e67f347cc73dcba5c1baef137d14e1e98c9a9b3006ac7ab4536d1551ffd899944076ddad95908437066002d1f1f4dcef7a3f4759ad3d7db7ce69f60a6092033c0a3878d5f89d9d1e78edb99d897bec011d8184208de33b769dd9d53660791d50784e6e9924ae2d8e8cebc840bd0078c136bb724ee672bba6bb2fcf448967f8a799e1f11794cde69a138f25aa5dc2a9ef88dc6c8d904f5e6fa2c7563fcd5ef9fc0d7e8d13c2762aafcbe90dc8d522e64e0ca50855f12a87481b0076e15a7eac5bd33858c56a84b8e88fc817455a1179b512cac8f9e1032b0685e2bc0b3dc4ed75bd1349107a93cc3bc3d9167b9115c21ee8469f771e6f8cd4ae6ced3b4769eab430c02db7bb6302c89cd3bca3935c471eef1332ce82025fb910873312c9fde1bb927538c4d0b25e76415ae464fbc473c389a9b7912f20b3e6bbb5270d2c5cc169ee2ec4b354d5078a02450b579475166b8955a389912725f3f5a729fb52560016d43c988a897d7dcbb8325a0031d5af54c4f0c3cf353e7ba5e25e10be32cddc6a3867801b1183d2dfcd4e08f6c336c1f61a334b37ab6b127cbe30ce6da5bc8695340c1a627f204cd0e0c878ee1388346519035393eafa148cfc9c6a981c34a6e765e447f1e6043988ed2af80855bd1a69af8f7019ebcf77c4ec1d13529d5577dcaf3d4cbc2af6b7447180ee621aceedc5c661097558983ec84ee8bd1b2674a016bba1f77264a0f008ddba0a2e040ad9675f5185b68594a22a6430bafce32b1965dae6184d7186da964c6de3510ba44677a8b611771033e20ab652de2699e6a8dd92ba0a29e7675ab23eb21d2cb392c62a2a70c4dfc837556b5e8b24c6572b64b54322fb7385c296cb9cc8688ccd873503fce96b6f93acbc93815ca8aa58402922a9879fbb445b6cee054c2219b5b1ccd8f5cac845a79684e1b5c844fda18534490138a9347036b42406d484245880601aa70e70103d1017086ee1e90d1444952cc2d2106fceda8c4ee7e198f602cef4f4a4e7f854dcb4862a928a4882759498b5b8723a5d4d964c5df8d42ba59c0ffbb23ec8b6aae68869cb88aeed82f041f58f0c46887f52507d142afc580ca8ba53374b0bd741d733363a013ab08e9ef46cc7f2bfbb0647061df3c0d98ee46f45ba865bb9f3f072375cbb0b3fec5d718b4724672722b2db51f61f10e33acc76765707dfbb20211858bebbbf2600d1c81889b197355db0850aad8b266c936ae79e9e512a77fe342b5041cce887acba1d3627e3bbaa16aa01b7cb04397cdc0273f2d126d7e22d1795ccd4912b6d4717e83840d69a4a90d8dfb19b760f3be3b0de15d716b74b30cbed555a4b6f07d2a3cc03b7b21f6e5fb4b7b123417e3837f0b7650707db87ee28f4c5998f544f2d16848f11618ceb7e369f7bf4f4a10d6644407af820242cc47c889f528a272fa8f5a2a4f241e4f89cf2d4874dd0ac071a6a8a005cfdc3dab1d2aaa957c924fe93ff5ce7cc3c4bc42cc541aeebc63416e0dbfd1309e6490acdfda3dee0c1cbff35c4d7ac0cef800be061c1519e22820b6167ea51a71e9399838fc740234f3c0d8328659f9727465248b385673cfc4d6c600413a71105c07ca5bc7e2f96ec300faabe1a7faa673bd91cde9ec9844e736774b812abfb4f2666d6628eaeab1bfbd793021df179b61d8e9ab1e768bc5d07feecf3fc0323ecf851897462c45b89677891f906788ef6e3052827f2fe99daf04b9d6b7d563ea2a72a0c362b9a344ec3affb543500e69ef7bd2dc02970996c7100cde739b765d1edfa01f5c59f92eae267e383fcc20fe671e9d173e1922750a52fccd3b7cde1ea66599f04c3c005426b18d95df08dd97a85df0cfb94eac9f3026b282bfd6fea17d3ed87cf5e50ac4ce32e3c8658f44ecf4d23e747d50af8f41686508ccea276db4585d8550c60b2b2266271277da92aca012c96867147a2344b59b8aef54a3afd5d73ae97e5730334ceae2aa404d85a855c825097a7f73a14394afd877313a08dc05631b0c18fc9f74cd981c6e0b3ae1726f0f0ca347bcf766179dc3535e763f7d67f7c6b075a7ec7c1454fb38c11035221e9fafe68eb0cbc3c6487c956d9294d1db5f92fcfe3ec48bdda1c4e6186852456fbab4381356f9e24b14626079dd26cad9eee1985ec83c7b71235e973708b3527706c5a9d0a55ae08f17ce4dc3c413acb955d5417118d1b0a1a2970e97a05a32ec2d6b99be14e1a007e0d6692994ee57cb17f61a72394a84020fe68e6059964891a9f3388906210c849a29b69ae7a56622c0c2b2f94f23529381a3f266b6277014650cb12c0f3a897ce42a324d35ba3e7e766620c02484214f0ab55bebd1c725c249f26ecee20aba980142dcc0dedf3a8353aac93b09719bfd5b641923f8046283bbb77bcc20d83c2195c79a7c1d9afa254d011abc4564cb622b177348ac2bbf0dff9b4472b97f8a082f962506d2ad017095ec9bd92faf0f5499380b3c05830ed323a7501fcd66cda0990f075c340d6aa24ffe468de4aa00e7bdb3b5094c203c1cb01bc03054a1cac1bed5c6147e362498472e829705058db17da094d19d039fb5e42a78a9575b606febe583f6183f3a6ce99638b8d3fcebe8b1c8f5ea4fbc86d3f077a990e346d3301d29bbb21eee2268f5e652c76afa7eada864a86e07335b8af2ce25ec0449d3390da7174951cf5bfa4b47f850be39eb6b8a1d2f5951a7e72ef1293b6618a24d1a27bf9538f6c2c85bc2b7ddfadb1b3f0c5add3d9b6d6f47116ab526dbbf5d0fcbbdf1028ed4e9b8ef6511057077a6b093baad931ce0a7fa4e0df9b29a29292d5f7a39da1cd9125b527ff04e531441ea906c90ebc8ac4395087e2063b4ac4b588e41d64a348943f38b6cd26e53ef7fe79fbccd1b040d73994115206e21431ab480e259a734d7de38903f845e41b5edc7633eaa7cc8e8bf0cfc29040a663e9c3f69190f8b3e96f996d68b03ea8797d64675d7b2cd8db2e901e96e5c341cb0fd374f4f1efe7eeda0989d16b093421aee990212300c531bec7d2f4cbc2ea1ca39a39552e3680fb90efcdd75ffdfae02ab5879d47d838dc1e6a8b55050841df817ece31ed3feab680c19bee7a836d70dfc16ad0028b5376fc2fa2aceda74ab0e4ca12f168e87bc112bd0c55058368e179b0a8b480f8af246e8fbadd76a66b6f6b7599ecf65cc834c2eae2a6630487ca5f1c13f63b0d000a957014183f557c8c17003415e49dbd05da76d02db069c32472b63b6f9f98468dfb113e25d7add1fd957fe1eb59c57f797591956eb0d4c17c88abadb804949d0185f28cd8e58a039b74ac988079d893034c4ad2a83c170e518f1a818b538a086d0714f7a26847ae785f9f75656bc6431af2ee81d6c7b942d88dd5917fd93eaf777c4f936aa99993f2c84cc752b08996575de89c05a1e7211e05685ce4976ddf041417b11a11cab8433c4637d0328819e1960a68261bcba46cdc5298a40fda6320577281de02588463f52b866ea80a20236ae82a6444a59d116b13345ace26ac018eddb640172af2c3188e869f390c1c05a1d272f8a07e230721913b3c4c896910ec3a2c48abad00e08db9f7addc1be04d965e88b66d4697504b1db6cd95e02225092b682394229ef99791915a1a2dcbde741c398b9be4f6a987db604bfae8a1bef20d0d20df453a54ca893bc14abe31126125cffd867b3700ebf163d57e40dcccc4107d9018d16b155785895e8ffce0cd127504e4b89423f7777cf95cd274273fff283e9026c2953ea050ee4999bb86337b6d631bc8aa2829ce8c8cfad1654705ade1c46a2735ae033c20ac9a351a03b802f0f8dda4a5a9155e71be0cb0c401457200ce599cb32e19b828ed544c9a31d918c46f97e9ae1e3d8a7984e6ca77397a6d984bf68fc8666a922b49304ceecff9646268011d353017840b32eddb493879f0a94a58fd74f8a2cea06f34e36d7ee4b6b92cd64d41959e0928fdc7d328084acbf2fffd48a906da456bb2576b9e4ff88ec9d30847e93bcd2f8ef143db3c9f55d28fd588d6b6ba877a90ad268247ac3e3f97d6c3bc0ba06c8935e01fadeb887024c89b133687ae0af77484b4171f0f9c13efcfca9c91d3b21933a19f6c1096a4db34f5dc828ad9360f58bd35fdd1c736c0ca1c1339e4df6c1ef094c1fa579b85ffab20e43bc64b588f6bb0821721508dfbc7aef34f1900fc537ec7b1dcc6088bf13c7c2adbcd84fd64495be5a5456326dd7c782288824ec1de1f67a54aa6da8a1b38a4050e7151f6f487846338560cf5a2f99e4ff85e63cf659fe6f79aca16987bd4c8bea4ddde7b97d42030a040e24e4cb4af7471de103bd4af8277d1997294733b132235b18d6808ae674d3844c729fa831505af65d6bea4e8325b951c238b6f33976724c03477864bdd2bcc911e91522ddf08d7c5b125d7b83997235452126fa99f1a2a1e624c4e75fc87de0f5adc21a284a2e58ab92b26b5ba99c8f9cf650d9ab9ecc1e422b82ea1c606232bca86cfd476903a153584665386e20a4e7c6aab9a8df97c0e96162b688f00f63d91581c8f164b75505cd2921af2cda47ac3d69c977a98279efb5c05e7fa8328ecef9c0530982da3fb548ef7e2c02c3ca1897bc98728c07fde2992c86a95d817e25153a0f86b099f10c07674150d41ea6b520f9a9785bfc689478a71447a51435a22c458409c8e92b0fc3f04608a1909367c1ade95f20ac895cb6236f62624b696e8381c8e6dfd95bbf54afb4025dc6c2f9f86b0f591afa92deda7481272d68449f1c2f36fa75a002491a42510852bae952fa72745e88657ecc101886d26a2e19d10c5423fead8b6f4976bac7c571c39443e7b05fe765a61c261df5dc2a2fe209a09b55cc20a634446701147f6680514b8dea71cd057ea4209fd7fb21d1e6e41fa03b7ef95c38f0eed5db03ed3bb8332edf91ad732b52b4873f3755516f665a98fe8237891d073ec23d2ffe157440fd077dc1bce529019665a2b46f521a1fa412d90b1a285faf102e21e9929154b784d97d7192a4b9fb94a38005d353555fbf8234cc3bda26bb5635f8e418befc596b3e470f37c333aa0f0d57c92abdc14ffa93d101f77a8610ddff141a817ff1c57b1df3f9340f4149d9d2869a231d13a9d5226bab405a7caff2f6c1371202342da48929c4919bf5951364cd470e3c18982b8fa4d739eca065e03a95fadcd762ce82ed15babfba74c8eb69ba397b7695ff78ec5fd26eed199671457b95fda321d11a54aa40d1f54d22a02ac4a0a9e1002e2a58384130bb264708b72d748efacc612ea8d49556c4a3d096c1832ab2b036f5a8e2140860161c299c834e95892f69a04b3fa44c2cc843addcbea48480aeb96a7ae6c7429e6485a210cfdb95b18e88f29708feaeb152f59f59d36aa713368e66cdb8460c2e4eea68963c46d49e978c9f589607824091383d106027dffebe52f58d66e6ed739707f6c518a93c508c1485f12bdca72af656d6066c574f938882ca17deb56508a8aa90d603429eb2384e863875dcf7537fb90f665dce370d36310352bbf79b656a6c739de5d5bd4cc13830042c5086b13995715b9add435b3d4a090275472d3b4418c4a4ae5215eb1dac52c3458a5289061c806747a329a0d18b7cb2fe8f680c859fcd08323cdb81c3144f70a24a9e01b49419a2f845254bbfdd3b99de0cee3bf5a35679b625aac9198d37dd705b0ad9a80747bc408a4d90829b4691ca708a67d27e45c465e09a2cc81def065448733340a2c9b76b2798f237d4b88cbe12dfc8061c879e58c7a7179cda80bdc9e51bfe2a53e4dd0b39381085ef00fa1ec58f556690ad853b10591b8cd4b9b1bd17f47ecc5eddee78db1f5df3d2aff786bd2768a27cb50920735c89d2376f3e8209fc97350179b86ab21e7a8a1a057a7292f7b373320e21343c8b00b40a371487141d026e58fa094885f1556d265666eae85600f647b8c1a8318a570c5da53fffd59d1cf968d38e515a26ddf4ad36553e3699df5e4a025d4e4f94bfad4f2637915316d5c0548f2011d359145163b2efa7beec4ea27cc6847afcebd4993367a1955c8cf8bd4a2fd53e7e957b094a7ad4d13648e1a6015a280814fd300433a4ab22454a416bda49ac6d27d9c8d4c940fcf09c0440959a2edb94505b802986c573549abc774cae705ca5c206e0c83a4710d0bda3437826d521cbb27eb5b13c6f1349b3cd6d3ebfd0858f25c920db7bc3e3abd6d0c207a36c0f2234818976949552066c8cddb6c0774aed06733ea08512b560b77771b2c09a81ee9409c7fb4851ca0624d7d08be27c9992cda5bddd0c705d206b456ed7b5f379bfbe1dedce3ed5ae732bae6f9075a8af135a58ca6971473b0d77129c9c47888916218ed34356e866d0fe436e621d863876a255d6ab7c5acca39653a028d94c1a83c5900f5466c2d7d692d43fd2deb66159751bb99dd1561a8292ca50578de4693c0f3c6373840895e5243b93d2ccf90af6ecdfa97cde2f4d9180a32c9758b5ae637f99d62d249310c2c201e0da23f604ba66fcbb87856c31a1904f743649efa0280b4cdd6e0f8e3490210f18655f726fa77447a13aa6ed7d4b702ce1f1a77409efd07c455249bbf1f1271560885a750d4bdad32d6bd9abf9c0a94c6b8f74014e6139ab3ffa8b685583a2fc697cfddcb3c2b52875e5bf4a5d7c7d3329aafbb994cfb5df03c64371e682b6fc3741c22bf025e4073a0688f55b7b1ee0d8c5b5ef2e5bcc3797ddb2bac31f80e9286cae4c3302193fe43167c580a291e28f5a1140c0dbe8e0771fca694f63c53a3622617f6fe492d6281ae6260bdd894b048e98ed60735fb5e7bb44542a938df6f69cde0766dbeeee0d94f52183344533eabba5918b18aad0b99202726f8df5db9815de1ab4bceae4663664adb5c7f8b7703bf0d35fb71c6e939c818d33072b88bb17c66a52f3250aad97690ed6024cd55746ab8cbceb0ca2837a686d347afbf6fd1ed966e372d7118078a1a18b72435c32c5490e08fb41d9bd5fe33ea55bad0b9b825f1b5fc25a733af938ffc3b971cbc5ba829e68e3cf65130e11fc8a36c6f49a6f48e2753bde714352426f02a0996dce3816e26a918ad4ee20c1b6037bac14bfd850c4744ed4682f498b05985ffaed0d6d0021697e49a08d4b38bae6e585e2fa8348f0de8f722e93da8303f4c07b64ff253e00fdcbd8bd00687f18828c9753461afab249f46258c2ba8bb5cd0d60ea5d6cb726f4bf6fb6c7b440b404a06ff0746a2d98503ad75c834e4d5f296c04c4b2e084139ef6c61992afcbbac20ad0081c8f6faa8ba9e1bb70b3214f3c1fde90b15924011e59711a55c3f354992fe684b8ab31d01a2350c41a8d3a4924ca7ee406d5971d5ef87dc3c4a73be78d235ffde3413ddc5f6cdc72e876c6e6c4828bb9a24c9d7a2079de675a9449a340b7949d988c270240a35078b007901786e04607276748e1df721adc2ddae180f10b3d005a2cc948c9f99798cf1545e05955362a0ab73d3835b78e5531308bc4460c65a71747b781dc419938e59214aac88fd0f0cd6bd3a9a45f8b9c87d4d3a1bdf1bc8bfbe79636cd59791b9028bdc6ca0ad15a4efde59b99d68c4c6c5d045ea1cb0019638c321fdbaefa44dc27bda50a48139aba5fa7bdc7d9fbd38a086729f2213ac94499ad81cf6ab3cd3c0b1414a37ea1fcef5c3f6c6a673ffacd88a37ba4f54aab011f54849ce677dbe4cd4e31d54d4bec3f163464d12eb1571d3977b5b5f98925e01a8da979b54d44f7e0875446e61283b599c74b75b579b42f085d9f334443faa1a42e8ba80b409bf1a0ce8f44f991847fc72e9968c1c3186a9470a4d9bca18cf7d334a85660416d6a156ddb5f23a1ad764d35740b19824afbe9d854fcea56d93b905df4edc1e6303d8b70ae0c566a402428b430a8a8dac37492050c6098b95c226d080d9574f62c6a4dbb170e24a79b0371ea9c8bf92035f50555aa41f788d55df98076955656250620a3154365a355ead2890e702ec16211ceec94c18391c758f3cc8b97bdb38aeb425375a2ec89d6aa46f74249efd1d89fdb583d11a032ca202b280d1034f6e55cf9ae2339b034f76e4ab7416ab51e13878ff978d6d0d8aa1639031543f36f83f673e5a52a0995f00eabf91751a6e327170c009b785806f5929a752b54e6f916daf685dbad32c79c6d96ca2065f041927e99836da18f794233a733c04108a28e45faf9398c5e66f1ba829200bce3960b082fc31595d26ee6d7e447209ab54ff8327a0153098cd62a415b040ad3d1fd476e1375927508c924f6b9ac1a2cabe9c43f540194f27d59dbe20180c29fa250f06b811c70ccd591d5380c10a8954bba2e1788c78b480b2ab36a673f0b8fbbb40ec207f6bbfcd10f6265c150083d178bd61e8e1a9722ec79b8d7b3ef4f74f2fbd99f67ad126cb08ac3d25d0ee4fad278c129252869d068427d0d3cf679409390a78ec7d41622e6f693696662857b09356b88dbe83cb8a6a58492994137b544e36f761f5a4a2761f430709a81bb6f92e6ff11f90b47026ce9e3c6d29d4f8f0ca8dfb0f264037c72bea415960c8540089c8cd861f64d64938f9b7b0113853e47db768ff752866e61c413a1469620c6308061073141d1ad8f953313d144057fbd6364567da7c32060a8f0fedee67290364b05441c0d2839b6566d4fd0f0a92567e3fac0f457e03e809c0d4adb454bc9703cc9b983b538df11e0a832cc65858b8badc7cecde86952489b2400710a3951c32a831ec008ffe182affc86e4d6f29040fb8eb31feccf6d8038695b6f28d6941643e5c360336de1f5fde96c6a17a37f511766b785e04fe55b185a7c463ff0c7dccae33b01d02d2f80cadcf88942fb232cd3c3f397dfacd75149d0bba89b1460475c1c144722b436e0c43ccb0aaf166ce09f1a6a6e9ff9c977c5e7103c67b14f0bd96735904852caa87fa9f0abc3941ffc13e5a5969ecaccb6161f5087a29e109ac70cc17282dacc438abb5339a0ca8ac6215cda2f1142913312112948b17cfbe7fe6d3ff0e5abd6852485d4863386a2552b376126e3527d2a381ee03d7c151af628904bb04f4a462218be3a4c2986ae923f33a8125d5c8e4e024fd7407bf39585e9f8868b17fa784e50dab0a47614394c3536802149e1109be143063902884c290667a5ea4f204f430e44bcdae6c0ddf511f54837f619cb46384d807241cea5a0c0c52883a250d8313f63191e8c0a9c76c7f104a3fc1917b6d5b44c3e52340f11e84691f88eb31ce822d4fdf382223d0daf2b1ef3062c4ad44ff236faf0e9546c1ddf841a1a8be04ce45f80d00d86bd8410799122e3d77cd5a82d58e2d09234af517f27c5a0fab7fc2ca85733854f9b508994cf41dc1e3c086002aa83c31f505613c1619a2b895569043cfd85038197281934ec838c9c960f1f509505f63920742cd0a701a4f058fa4beae8f65287bf24f60ae445916ddd3ef395c3de172f6aed5b0378c9721255d60e8f7a906c396d02a8b22cd3b04c1c5c97b76e12abecc8828f3508c9a49a3ae0dd6ad8f48d1438093388cae546047a3f373f390bb40a2d3dabd9c36cf8401c46afc281d7549328a6b3ea470a70c25137e7d6e02c18025d9a9562b1e35e994dfdde7df5f9dfafa1d104adfd70abc6ae9a511c0ac83e2963b6c7da07fa699102cfdb4c9bee09725e07d537c386bee196047b7b80be2a50a066349a39c6a50e3030fb145d0f56d3dff7e5dd662ad1e4451aad5e6c298c83c5e635ae59d91ccb0c1085940bf330a9e911ca303a5cf1a2ed2713a15feafb4275129d5a787db5385af97fc86184e69e529da3ce7ab90bb70f141874721c4d2447963898e83b923d92a759c5d62215b4fbbc43696624fdaf54aed18aca3428edd19c2ee47c0e0264538a26e544956b315ea252e0941f9a46d0ecc561331d3bb016aa72dbbe71ac4141c5ba3760b894fcde54d86ef8cc01c0a48801fa3a29a206df9d89e43c01f6ad866a110e52394197d0c6d204d22f109a10021520080cfff2289e38403a84fc363d40287bc9fae72f8802de6aafd4acc29442f4e3127c7a94a36113dc29d0022487a221331acbea12cad0e77480aa803b6f6b44b51b4c1bd441b76690a40c11cf3246e7228754d21ea7323ba4cdf3884cb68d5689647498c1e0b1201d2c1c7bbff9d8a70ded02bb2f378f1d16f78286ceb7b0daea8b2a7d60d0a3a748ae1847cb573545d3cb24b0e3cb824ca834ab6841c4150fce4c41bb9dd9194254b1c13ce7083bf6961575ceb531b43b7bbe336f8a64f4c6dcc0cd57779b50a3820732bdd69ecbc2cb7816b65a0d8b86766542c573aafd010f49c6e1cf32945dbc4abf397e17049209079089087fc308d5cfa81c607205f67c2f461a23614e08ca654b6c2b10cb91b73c46692920121eb8f0ced05720f379715244a707f448bc7d67506017402205fd3deb7932c720e67d6308c55a171b11dc1873a216778739bde502346b9317a89252cdaea0f27de23dad56f5a218e5b90121836d5ef5692d1eb7fde0c6d82d215402027990d3199bc695fb0cc69c85606784b1e3793fb54f4c0e242248635a20614f5ed8fefcfd43eaec1476203016fb8e61a692a2917333db5888de137a0ca092d792942573dd55c115b345c1c672f37c01e9f244ce400c72618c3251f3beeb793d8cfa388f76c4e7714094ce857436ac90131dac1dda12b46e7251c0c194500e055009d9020a3e3bc00b98302798387da4b80f4f92d13b7e7c3b2c5001a83b9fab08297a6b12a93e7b5b410627274224224896552c11520b6c83006aa26d4b039a6b3f8f6652b831e299b7bd50d895814d4f6c7a118130fb8d127e1628509694b71d199e05682cad2508abd6bd22220759c9e40ed3de05711689bd21864ca77ceaf00ba9763b99318194ab0cd816169537d879889c956fb6809e1001bfbd2965c191acc4eb2f4d555b76939f9128239b4f284bfa63a3ebbbae2842fbbff7be60702ab667a535e892b39e982ab9b3a7ad1fbc4a92b141563d59043f4a7689b43a048df5deb9ab2b6d67788f29417524151e48cacc65297628922c5829ad3f43206188b2e1247175f2c3ff6e712cd01e10ddf47e071d49389786c6b0d86f6dfa15ca443e0302cb7bd3243bc84ca628193e704831fed4ae42f17a17263874640d7ff141fd7f721a16b223c075873858b2b1a3ec80f07472385b9447b891c51e1bf6f646a31be25eaf7cf735f8ca526f0ede0f337606288caa62b92084c15f14c2c0722ab443ab9087c3013aa00bc5b0343d9ce904dd3e58e1059017bfb81ee33250c259e0b57cb0b5f49cb11db0506785edf0a6fff4e32b526ca6ddd70ea7fec14e55dc920f12840c94de4a4bfb4928f7751a9ddcfc0164e7163a5e07f28b83a767d9bdbfa80b8485464b0466d95e44bb7f618621b74d6b889e8b0ebcba4c03d3a539c02e596f682581264fb81980566182800c9fd84127c730fa175ba6eabab033280c37888eb1206a031070047d28f0a058084c9e6cd93f05f648582228fd80c276a48771bab0a72e048487f51402f3a30baa904ce9f4f658593394322e9ff4a6dd3b91c22dc3abbd65e2459bd1e2b328a0b92dab6286b6e8ae643f413c2443d40f1e910a6f9c59890aa54f0c47c45b1daae8f225e7f20122e232469a8f61809b59b3335129ff4fcfb4389fafccdfc978c79ed5ac77eb587355a62f7fc9603e4e921b403f4c485477f0358b660cef7139babac7adfd08824f279ec117ac41abfedeef530ba132f52d5e972bba0f8121555791ef1add111203e909015838cd1b1610403c36dab0146c6d76760c089642215811d2b6e234a8d3366400c89f24b7654abd948d142a51ac993f383078eb86071bb468e739e6c4a9f03130690345b98387919855dcab92ac32fa155387914f1949b802a022e1ec81b3d705688cf7cec0f9016bf72bc92619b24e5caf5bc32b15fa30a026ea0a22c700ae6813d064a6a8d2ac5375832164805a5f8d6028f4cc3f2ca6049b447a3943c80ae0049448e2554a2c23700352c0dce88967bd3160505583010091664f54605ef8f01d015ea20a5a7b36307d0032fb1126887aba9e80fc4b87bebc5b960cc14783bca43604cbbd806506b30153eb388233807a94a058a29dd2501b88aaf1c9d25b0aaf8fc9d8c310901cba6e6a40a4da9a2058df67968d38f80e3891024e4bc6021c84c71c2228f993495c5878181f5b4c7efedba56e080c58eb1e49c0c3e1b9523bc11d631d6f60ddf422d9a8b372c8f6cec4f55745b5cde2b2bb9f5690e8b66b313637831133863d4fe61585a34771aea4793bff8181b9cfca01f20427d5cc965b9e1055381ecb801b05506c836e148bfefa01908a3471e8cd8dfaa4903da0dad2b8ef53a2e73ded14a5153a1bfcacb4a0efede5b5dbf89a356e03f714d17e18f8dabbf743dc8e429243fbf8775454b1f568636cb1fc3a4c27a332696455e2c808a4af252a80406b15f88718f9b4cdb26f7d7c87302e7c520aa6ab296ca9bbf03f38cae5b3344efab0034aaa1afd36c1b50b6286861d6d641f13bc0bb8a2cfc4e7374ca32fd7768ce1d32b0a0e7c79b32e114525794843142e616b465a2319798b8b45c10d23f94b234fbae0ee527c70a29ac4db65ea4004ee5eaa601026be4941bf0bfe758cca11c2084d5bb83d4ebc04221dd2ab6d48bebc8af65e5d03746fa86962ac2cd38af5cf9feb138ac36291ea8228c0c4a4d595f91c796c6511aa8f70c126a7cc9f72744aaf13e3fa029bccfd798a54b415a399677899febe471cd6e733d86c9537f331e9073b0e2fee030838194ce342105200ccdc55367d726dac8ad25ee5aaf3db2ef2573825929017071b12e49603651a73b80824b2e23893c8a18cfd7569d69fd6c90593450ea07d3503430804c5e4cc22959d0d4b05c16ac858ae290f48aa4b9df5c5f5c880a46aa8ae727cc33556ba0dec1eec226a3e3c6785a08713b7a49c0f10be7f0e37d448f00c8fc234527bb6bc5de84adb7ca236698062fd191df7a44556dacd778fa98ffdae73cfc9a89351f0b8222edea4c586d68e0412728c3649fb22d73a0c80b018f8e4977e75df58084154169bd77a5feaca03a60d32b94aec91c2a0a66e9641820099d70901bf6801cff2dbbc3ffd6f3134ec2770977549081c9852639be378cd87bafa3e1334345967afa224e5e0955462745352ee549a82589c7a00a33c7c83234031394544faadb9acf6854575daaf079c4ff5eb2321a852c02470a4d9ff7c0ce6d3f07cb746402761f2d77e61dbf4de7b7f6843aca5ed1c128a38089046ddeab29013427868557ec09b4e0c2e89dc0af7a19b303e0ecec252c6f507afc4f896fe2e76df948ac7bb0b4dc046ed717d321f2c333e086c0cf3a8ac66d6868e6a5847e66baefaf8270a02be93407b4dfb469d48e78ac4d037860b43ffde789c29b4df6eb6b2a4c221c5a6533a07599efde572afe43016e2ba61bd905629c099632b37c1bca7a420f58fe5b6b5bdea3a9505fe5deeb0a77dea0817707e85ca27194a4938026ee93dd96e467934bc9e3a8905dceab96b70a48ae39869b2a6e2d44e509aa20bbd8a160c7d822aff2aa6f0eb3cef9e36b1f6e1309c830183dacc42cf8f263768ca9f858697c5a266e14d4894a83daaa89fb60d743a5873dfce6e1ba32a3371e385d028ef80f926ba065afe82ac32f6070e9c7b2d22ce1a110ae508c31b30d05ecec0903221b5c9137cf1ec48d66d01deeaf24538c22eb44011df399522890eba0dc1c5a0b52c4a1a7015d8e7a1adb63dbfb40c8b1d414062bbcf80162aad4a0ad439d2fdd7958b51ce94616ca8947409ab417a2423e154162d545ef145d63086855772453c80760f3f72834b3fd74e6398bdb091219df2c89cbe60f309b77c0b3dac519b2de41fd5b9db79a6dbc01a9b472c3355b54894ab9cddf9b9a14a7e9d46e5aec61e2dae4f199dca997362539fc7c7c5ab0289f7001de8fa673de807ec1da630f4f6f67321dae445eaad3f00667b7695cd3dca9222b0284dca94608e928d72eee3a7df016d6432b749478a70f55b514a2cd7c4aef472b8c3c6beaf5e372c10ffb7afa303b5f0c77387a01d6c3cf65c95a4290b397ee89670b76ce062290bf85e01c7742508f5b65d92f18382d6ca48928c241a92c00d16893cbb02974186184cab8917ca0471815f5609e75461c80cb76f60b38a88d785d717ea8e99f5257045b6406414bb1644c8822dcc0decf027566b5bd26c5f232d40675406af35850f983e554b3839df0b0b9fabed49d842938a2155305dc8c0db574dcd79481f797630c585286e579458d6f690cf169914267186063e46449c0b5db923d3ca14f5483cf35663968bc1865b34e43a923d29b71d84bb55ae14d4d2266ff0f2b382f922dde8eaa1570ec0dc87914346138580c4baee63b2581f4e22b043d41464eb37ede7ddafa92dcdb9de8c2ef9d9041d807cde78befd69eb545018c9c0e7bc7a08bd291dfba3a45068887303eff695a3eb30efd6132d5dcd66cdd9a03d5052030984088283a4f5110bade028c4b5dd39cf54fcfcd84939e58a92aa2c1d004045fb851f9ee701662330ab6cdf5abbff74c79384593d14557896c9054d43ca4517402b3042b4c2f2293fd1fd953401695eb8bf5213abcad83bd05f5853f10735bcd455d7343c0364a31dd3a0e41f3a5fbcaf8df5b492529fd3c8f959ebe24aa7162200ab92dbab1d377c9d60a698b5fcf8559ac75d9374826bb9e12bde5aaca7216c09e16cfb103c8ab57b9fa0e516ebf84df517260aab86efd53f2607baedba5279cc89ccd7676c9fd4ab6e728c768da0e034f9eb99e5263e85261172ec87dec4cb9617226f52c38443cf9e0f7f6bb81ff8f3dfe0bd92aaca084d298e95a5b74193af99baece3ae0b438bcc70bebfbfc6f73f1620e39d5380cdcfb8c4be020fc2ad4c37a2ef062cc5b5793a111f39df18e0b7d4cb0646e69c650d7309758257c07355594b9829b2f7ad819a5d32641aa0c9c4997e63e8938872749fa8a7f34978d33bfefff85784f92f4668f61180b6bd463212c560dd82f89fa43c481e0709f1449e4c6e7ef2b1ebcf693c4e5b581f5ea705811295ff3bf950b8aacbbd2eaa040271df449e60dc3a55cc1c993f479ffd741d4c33ded1bb6450d90bd2b560a0dd6ba0a2c0b7b34d2c468dba6b531bfe4048899098a4b0a52f03fe529d4e76c93f239df9120131d5c7a1dd0280248e9e0aaa6e49034861ee0e08d2303ef450aa0064a45f37c332d4563c87a5da3471876ad07499baaabc72fe4d29db2d2224aabb851e9f2ddca6f9056ec2db6085d23b1e4be1b577b809442ed2cbdc14c803d5d5c3352f34cf4aa45f863bc958393e7840d163756a5b1c83e636351f914571934fb57fbf6de78d155f2401d2b595e76cb0b86bfc60bb6b09c0d6285da8b53fefa405997a69f01eb7d1a1bf9175f450abf8b7fc8cb3b520c998204000521454a11aa78fa8985b1c3a1a6979ac977e6ed4fd88c936d4ee2c52bca1f6181b8d3befe0f2a94871fb3d5172331cb5b232cd2533fb76c755e7f1c61df6fa364749f11613cbcbe88e72c592ef3f130fc05ded518355f6d0c525ff08e1bd80c21f2feb927ce400bad31958316fd47ca0f740a3447c9c24a2e710ba21f3a206dd92f3c8dbb0effbc3e8326f97dcf0a6e47bae1ffbc24eb0b6ab8654ce4bb20f62884d2cdb8fb997be13240257632860fe799a36e7dce6991c77e6fa326130d690960a2dd331d6c00880def9eb15d010dd6b2d1d75ced0994ab461fb1b7e94a0ce852f1c0a8144d0b65a44ed0f901805a1a2571153f388c73430844a26e8bad3921272a0dd1810021c852b06f59d041e56dda76a89eadd71208ab17c37db00adfef45551aa25a26e5415d94fd8dd56d7f842cfb1cb98cfbfb7fadce5f6fa0db2065bffef028909209c9a105bd861459dc831ee4d24bb1bc162b34ae6307f8b8fca3a77e43c2a66342777d5d27f1fc37624ac70dbf600a537bab5f84d49ff0b5ee47598edf94b8acb603c1ab6eebb23447150dac6d11c65ae4ea7889cda81763f3c195a4a4f62db03c67ace0b13b512092a0e733f271033547ce50d2417206355798ef9cd253cfe70c4d57cd1986ba19ce4b5ce1fdcde2915b2398e24b24fc3001a9f2c63dbcf6ec9fa839f14ad9833b8f948a7a0009e43d3072201c7794defa29a639a4d8fc763a18b23434a5b81de0b3a482c841d01c18717de699d37e4cbb22cdea1030ebbac26855375117a30ba50d876a032ffcb0c88ee33839ea0897d6183897be40b2a243f73572f4132f684e8672e11cc4b8e527975e2c26ec436a04c32eceb441c8639588382c9f14e3272f2e60c8dcd38d09a2aec028e2183bd18f959fdb2f670f9d04bbcafa728ac7cbc53c95ce1803b98f94a71d9fa6fb35874d29e29f334c4a7e3a685f55a2e3fae2d063f54bd315e4aaa6e9b4c5d36e4c9afe3366bb6f6cd71ddfa78fce7920ac15eaf53fbda9db05fd4bdaf4ac0693d33caaf372c79653841b356470aa2786fbdcbbd1ede9a38ffc8daa0ca7d752e04bd0fbe175ad1437ba87d4692d02c660a25390d3014b1845a429c4d2906584f250d16025bf1ec87cfa3cb1e14b7a601bbac5529f81045601ba618a42fd79b8549c43b1f6f5d3483f955812c04c1a01a580391d955fa4498b47da10199a1a558452f001168e37907d539d4844cb89f4aaca3951c75ef7de2257f6297b8362e75398ff3da0814b075448c35a60714ae13f2c6317bed343e498dbec8b52214ab5fab492e6ea85b058a2d3b496849e9a3b479dca289b4ea5d887ba09e925a3b11a98e2241175ea6d62d30ac3e7896cc0d0f4e5d11af4fa851f60d697a46de2c0e6f428c91ecab68646594fcd5c5ddbacd1d6c8a91d82f1e4d10ac607d52f06a1e4df18dbb0529998843663443634b9b3f483e741f7e1c541d22ad11f1ef1fa294927b22141a237b5c25b75aea57f48761135d6d30845711e0f7ed50bf22e7c6c11158736cf90a1306cbbf6847f4f9b37c7d0dbdaf81c777bef9c9b7b5f3054cc0cd77fdf9b2a4e1a457b287249a59ae26c733d226380ea5839129d57e43cc95091d431695d45d7bd185d18308946197844c8f08b0d56d1da31c8c499ecec5de229c97a593a27d0756276fb23e7944ee5897e2a14374cbe7cbde9e9420f59ae1c4b9f059f94d0d5be4a543a697b4d568b97a31cbb6539aac6744168b22bd0f788e61ed04606962ed88ce774ff1694a252c79c50e27c9e86f4eb1ed34628f79b4b3d22d24b096dc25230d861842c2593633304ad35aa8a92851d55ad28274aea14087cd4a5ad40b47b589f8e55888128e70151a45d280a59509413b1d12f5442f6c0e8429363610dc93e98f8e468b5d9e2360dae16df6e15f4cc39f37c4efeee97898be3095105b9f7f807a3770600c27f1ebf9f1323d77bd2ae1b5d6bd7e5f8f4ba99f607c9d05dc301c25f164cf3db74df7c2cc0f74f77d4ec60b2fe26acda30bd6475ab320096a908bcc3398c8d7a4ea4864d67f32137d57cf4a51723831d5f46f2c755706f0a2d76cc898c7aa37db1c04df07d0b037bb36943a822177d609a7b378b0c91cb17ad480db0827717fda52c68a567dcb937401777d62178b16bfc14ddafe83e45f751b4f06789720f346db025539462c341aaf4b498733ad60630ea61299dc20c6dbe71bd68f79182b567fb81bb5bc805c4194e147d78c17d03a55f368fe74d49c311a2e7b36a4b54cf066f5e71ff0e36c3c2a758714205de6f73d3f1fbef079def87fcfb53ce02170f3ae175f0d327db913fb8de90fc1263c101869603170d4aeb3b9dc3813fa98f383a10a2690a6a74f5571f94ee4a8d86a51bd288c0740f1a1d4d77e0794dfd31939918e474c6c74fbb5055430c4c7d7601f3200c0a75a5bb317638cf5f578f73f2929555ba8a5719412bfa1b6cfa3cc7f33b774477214ec93eb41388da6338fa4017bd38a127a686b44ffb763bd9a646d91403ebe534d4be81816a005be52883325226b232a18bb257a3472ad51be05650f064dbb3c10395746460bba9d6c8561b26388b946c4afc3e2c058e489e8a2d9eb1b642d8b427f46ed6e30ea86ed5157d624d98e6236d6cf5e1cb7a77dedb468f542e9d43defab48ebab0c78d1facfcfa632e51d48341f40637f4d2a1973e5b1feb90223b03afc8cac25e0c0783e8754be789e122447fd0a711316e174b8cf4a2f655e45a07bb4922ef246085093555beee6ddec06abf84ec7e01264cd89879d6851c219e0ea9e2ecd53a6254f4ca93aca70c6b5aba720e7a46924fe67332f91ddcbabc6d7bfd454fe51c5751de84610ee3eaad037cf4e667ca8d932d048f23392e7f3f0e052a9008d2c5cdc3cf2c3563def0adad2f1a447621f72a54d3af058166789652093f533d277acb27c3ac96b7f93ad777d21981fe899e465866f7f752938499860c82c9e408a270c81d673c7f90c2ea92fc165cdf4558e041fae8798d4ac5c4df8c4ddcdbbdb47d0124618dd356d9719d8561f33e8fef797c4fe0beff3d2d448f04923a41527e15b30c319193b74a7f63983d7d23e0e9cdc54939ad31ef6bed08fd2c3e80d0b9c88d05739babafd2471a80f1c47e241fb55ee777dc5f454a19863085faf76680a803ea07077344961160060eb92e876b066422a2f35fc5190dd8c4ca7a58af8014d1d9d3d1ce3785f86ef06152d0ddcd455b9dab8362e9e36abe9abb5ddeda1d6f08c42be2949eb475a05850713c447c16fac9a58dac2f262ae42d1c07199da1b36c5fe05799b745482295365a4fe5b851f971b9a3540a66f2d1f943ec2ba6964715db81b822ce70c273bd01b48976a4a626403020145cd7f3bf60ba134b04be876c3f260ec774175c8790f0b19f66f4a16121fbc7ce2e440810c5cbb5fd08f06496e80b4604f73f18761c36b7b020e8e9d1f814080585222653cdcea78121929ef2e18742a1b9581e0f7049187662693f6ae2fa28d811341e0bd49f2f9030abb083124d72b4cbbf8d5ebcbac459de574f37ec42ea2ec068dbd29a3b245ff3990cf2fa4bafe6a85273b201e58638263bba564233c8ac113f21ed56b1a893f15b4ac1e4800e16aa2ed67ecc52c55cdd84a2987fb18e2ecf7d524c4f61aadbf9e029fc6fe7c0c11db73c73249421743729a4f465ff3eac0653d6ba02d1cde55403d2dcbccaad4b31414f92fd9c73713c55d810274b3efc0c45ef791b4e73109daa4852709840cb2f03f3f991e1c6c75803e815e2757c7fafd06a6a58a3c158c48cf04aeaef0b594b6904c42cf3b968fe2ffa41240baf842f8020b58d41dba0a812ef57d0089d7b9496c4659a37381691633cb7eeee9de2e45c655d01d3289ab6832e1fef6010c99b4cb4f0c0aaf226b1e520592c77e094709cd2521dd455b5091fd096d22aac5d647d8ad65d7f4a1e894dd2a662106468cb4f707c258038333fe5f31ee3ab950c76380bd549ab7f0052f9d9ebfce81f1a6f4269609fddb6411ea5e7a5c8f69173ac5fb3377ea9da58197279d628f8011d9d6aba84fb9a9a4585f1e7c6ea3168e1eba3054f28814d3c3a18eb835ff62e58e5c6f671df27813587f9aa2f6dd8cdc121a8b10252b2f056086d5e1fe09ee47033f485230d2f123b2daa428b418a52be52ed882cbdcbabc9265d9d9548f78d968fb8e0563929902c2d5d198780a0913793ea669becc408ef754433d14bf3f76b178211e1a49e4c47ed7655f2b811b11177f7039d2ffafb3849a9285b3c96be6e67e2631ffd96d639e4bd68a5b5cfa104fced91c0149a3fab9b70edfa6000fbea5874b68b9c8c96c18c81b84968ec7c21a1294a55ffd11674b72cc593d2d43bf0d82575542312b82db9f68747a9c184481ff3afbe21ef8704bd2844a1cd9b673243f47e0471fc518c3c3af0e2550ae27fda4bd1bd2d21e5b9fd5724872ffc38043568516481451f6174522041014b1398160e4b5ecb90f24a2a9d0d63419f27907a57dae43cae8b0480cad66f0ef2baee9388a7ce59e30733649a125a546b2be306ab2e50ebc98124311bb09e3fd8ec0f4f5e0650ee42dd00a8a5e0ff83788d45494bb628ff5ad31d6c5d813ee33ab22ba34b076ad7125b11c11326f832a036d979ae0d132b3a715e570e827757b8be69525dbb6b5eacb7b5db0633099dbead81325bc6d694ea8fe5e8b233aa6301c1eddec0d337d7f736f6ca131a57b3f049c9a1bfd3fc393a051c0f3c5627bed36e50150d58a6cd2d3a183ba5466bb689ad9331c260030a774a2c447b5512655c409f50472f34c114218130d2317940228c76ad4c96e82a686044c2cf31de3e0497345c4d7238c50fe0d2848d407174c11dc201c30d8ac10f338928808907e2f61375965e7129b6e5751cfa683bc73e19bd14250d0aac7bd9b0e296bb08f7e49444132595224ca8d2f603ae462b36c0aa7f961a141e14416fc3c26185bd3a7d43d55fec34a5bf0ad212bd4e8b1b38564bdf09977d2d3cae10a2a9c4882f1846f49a0fd6b388d6a1a84e9248d889f840c34ac71011024cfef5456c5ee2babbca3d4e9db7e780136ce86e4501db0a2cc2c10dd6bfc92c350c79a99d72b798fb84b57ac67593dd9b1a8cf71bab00746262f00c3b9ae4e2e7232d29cc831c15198942e0e2f0669692145f2b8ec782f889b62710a923526dfdb3b1e88da9129ccfbba74f208d9836718dbe0b7c46773d9f65ef470027310a2d42920369a0b0a211aa62be10b85e76960f9340fea030e66a1c23d3a582db1c35b7ee86f118041f10de63b4dbcc830e9c7cea5586dcb8fa1bbf422d19d37ce30ca3c5815043ccd50fca572643069723c644edd75aa6e00ad2c7205d5d3b97581cd2ca2386ca9f3e289798ded04d694de8f65110c6ff151417545aa224090275e71bbdf560777153bc80f254e5123e540b15a28848f262e1239cd2f0d8dfccb5e6ae3bc0f23c3f2b726406ff5c64d899845fbd8e7ce38e2b7275c652b456b79bf1e5c67384049717e61a1d172709dfee8dd012444e54e72a30f648566562e0aae529cc5a5853577ae0c88d3968c51cb9ea20a9c8ebac2f0b76a568f561c9ad43aa26663291bc9fae6d4161123739243fa4e2d67e5ea0e36db4922189fcc1bb56bec157f355330ec1d2aa846b250aa451115cbbb713b71f57f1ff96c13822286320678221413959158bdf449925c84aceacec7b9d126f1f06b45137d7c9b9d8078c9737c86313b8610c543b9cd4a778a6e53ceedcada1911664c63a3c96347944a8d27c0e7e7edde5f2266d08b35874edadca64b6c7609aada0abedef3c0ddf7d2dd95be80a1dc805a6cad2e88d0c056b106772fb367bc956027cfb7f50c62bd1dffab46d71cb99c531f8c394e41721f1b38f185e5195b26ab49418bf45599897d89ce83afa297defa747afd7a2854b952beb852c751ba0feadf9bf7cb62b9f1f6569cf06edb50cc6079568de2daec36a4be9424c985d92ac9868248354a42c39db7f218ea152563010da97e87e63fda505a41d7e4d159bb72c0dfcd7ee9c364cf9858875e25bf4a3e493182df162843b4884023dbeba9dd80e577bd7dcbbdf63da9880835c96f0ac9e49c08907f63e52eebc1b63c248b4aee4aaafd9dd7f057041fe4cac4648e5ebfa4e09f73cc272bab0d057b1fffa6ea628952347a4e625bba11d8e514440935d6f5ba41d13399716ee65c562574d8e6a176533a87214657f463ee766b6f32d76aba2b531ddfae1434933bf2a2051069a776701b072c3ce083513de853f7f5edcd52b331c6cbfe8ba8dea86924e042353a08e30149057270662a782c48a6b3e0c16414b84b7ab88e13f9dd8c107de85aa4756e71b1b26c5f6c985a6a49f3bf37073645d345c488139b6a888ce3ad6017b383364fdfe793b17eb45cb6558bf97d51b31857f23254786e1d0c728407aa764d6f7c330b17dc07bcee5c4d2cd3654f19591c1cc9a54b4b80635d235dc105353e531d3852a4515695fbfe324f7b958b9d2de300a1a8d9e0c70147bddac8db64e4affbea53394f955b8e4df311ecd580fd7be413c81c558525a5256678e7c30de5f593585fff66200e16026e7b5fd0fd1c6c4f30fe600e6491db60c9137babab2f68af412548d5d35b25f6fd0f5f250e31095c17af51673d2b2d8491b20a472e673991afe620fad01f9f21c6cbfb3fdf208aa2ea69853ca1719ed5712678262a917a8d613315e290063a9b791d6e15b1ae6b4b53ec78fda00a27f4c87c13f0c7ed3cb079d122be08187a65e853b342369ea25a2c1709f27f12c51e27ca62c4310aae1e40600aac6e2ebe904f529f5f6821260988452646f7c9154ff7e2ab706bad22ab9b251f0446e3182ea523e0cde655cc9ba5970e201ec0cbf0222838eee534e25454b10e405fd4bbf26246b80a3e3e80a97ab16594e0392ac2ba2a8be835a0300221febcfca3dff0166a77edb0661e170cbebcd9370bb58f3567e6b3e835f559fe5cda3ec123a9b40a5c26211bbd58b3209b72448f3b037f104f3f88d72b2bce4b4260b29ef45b9e8f7ff6f63def9ec50fccf405b5d656efbabf8fe27eec9fadb03999e00480c3fad5a8b9c8b87fc28aeb86dc7a8bf54004c4e4b6f7105eece051f63f2682bfa8eb35c41c31354bcc6563121d2dfdd6a44acb05cb1658231ef0a24c55b49d6e801a91132d404fdae567bf52c5754b0b323f15e6d2f4e819346ae04482c2ff81565de24e06f89bb7886f26b5a1b0a4a95744a1e7ab185332c5c99a28764cb80a93997031e796da78abf5ede17372e8bf18e4fb51f509e84cf000adb3bbd763ad69db31c5cc3785b13f3e0d02f5ccaa42f7271416f5996a7de52f357e26b9f0486c669a5a7f0ee58fa19456f5349a557e7e47b58256f05e894b5ee7cce2469e4008b24520e7e43deb3f09eab7642079d640c515bfb1e9804b4c28883613dd94789197770f0245cd0ed775864d6c2747e9baac0f7ef1221ee7e9f624ae6a989e3f0404a504dbb37ab35607765a31b082260c64bd94184cf02766bd0a63eadd92d7cb0b311af2a3936cc4cceca1106349e8b5040dcd278fe55e359a6593b0fe9826c92fc161f5009a8cf56c43bcccf2f3e768211d285e6c669b89f8509e7e18f08a7afc700f7e2bd04fe7a9aa57bee9d0dce8141002f621e81c654a688ceab5127b45114a1ae093f05f7c2a05266226d1c10e3309bff82d916ca9f2c6b4f30cb0eb7c4176c1a913731be8e6744a01c1131d477dc1a412ba8dee4c493e48eec53e296788f37358e837a8d7968a76619ba5987d7aef0f619a60d122b193c50052a363b2d465f57b77f65a70443b594fd50e7379b1ce0b46711dab4b0ba3c517cea2ad2391b82d223625b7193ded9ebfe0443d730bdc0114db22fcf8fbfcf3b3bf789752f0adc5acb78aafa0eba5cc1adb8495e4c13bee8b92bc895eec6330df3fe6dd3c361693d298948690b436908b1760b52f7f9e10115b39a59e13fc064674f5bb134beb4027635f60f79e408936893a3d0af4714f993dc7d71a958ec257340ad64295635c48f4744d766343e0bc7639836b47cf1700fab282deb3be3a46e58e5b32c70c5c0ef13b6601275bdd7c5ba476189e3ad9a6e1e46816d2ef3b478c9db2d00d962f1727a61b5258a665f4f6260cdfbd69e5f4bea51a2719b5062438b18e76e4457cb429b84a989a32d5862c39eda5bc3714a0c44b22e3680101e5be1b6ad8846578e96dcd292d1aba696fcf2656f87b0a3b12caa55eae22b793ef25636d21d548c8d66d1d9b9112d05aa254b6563cc925737fe588ef23dd28a3d5f3b790a5b329bcd961f45d110f52b036f1a785f5ababe90ed5869b769bfce83111e78231ed40c0f23dcecf94ee06478a0884c7510c363d645b4d7d4d4a4a68cbe452ac69155bb2a6b0654a7d20e26492dcd6c89cab22c197783d9ef016eb1bb82c7b9a2870e738d52c891211f8e974a44bbacde2e30b18ec8aa08dfaf7e0632c78d6ba99c83ea319ed1d5529c1c1c50d7d4d40f4015386094f24fb072345247bea0679ce2a9567317f54f479a8257a74cdd4719564a90688810aa6a9e348192b0518bf9be7ea76546fc53569bc23ed4d2195cf6aaec8e9130655ef80b7476c53aa874a9a32c04323b793224a509af25aaf626bcd99abb26bc37716a31ac84a40e92f5c43f7afeb6efb3a5fd40cf4718fa2f5ac6f7374bb13a2ce1676cde41744691d4442950cee538f71294d2fc4c99e038bbd78aee12f3492da8363437f60c05282e0381c85d9004133430470525b303f44a476d062857191bc9002ad1c87257a864083fce5551cbd7d2c8a9a86b34408f2f86f35491cb06399ef24d04ccc39b350221e2ccb09386c88cbbcf6145730ef5a695ac83c35d8f822b67cffc94165a11bbb163111e88e1636b9ca8aa71ae24c4a48272035f3de8234c61c0300c48528256eb269092c5ca3a64455e11d8c8173c72cfd3ae7ce4580f3a5d3902fe31aa1e2d98dd7eddb3e93fa87f393b1f382642f7c36b8fa681824c05687e3d6caa80ae79412d21aa89f03b31cc98312589a090bca85b10478f155a55c4216c311706d17fa30c6375ef3e02c1d2f89d921d3ec348287ec70e5019493b7cb336637e9dbf741e1bc494e2139c21984beaf0d38c36fcda8f3e3ce11661a080c2c53f8bd6e51b9707d7a03e937c40d2ee731ab60f670ca211e1a72689049a0729e87c20c0ac720e1542bf44f8201d21d7032e5f37e785a9d864c46291b2be8ca13018ee1910727188b09bf36f5041f7290d6808dc79ec6dd0cc248cf073914dde697625c096e2132bde9502a66d88342c7e7e7e33fbcd727d5ab6af96f7d552b6049bb407abc5e47baa85cd7df24f73ece0360897554a80a33da506c2875c93f8978fa304c1f91881b053d7e95539061e3e1711d1da2e1838718258c1055b070475ab27f8ee616c1ae95dc2a36e3162b7dd414b7afeaa0870e5e895290adca8642f712df49ea3744e6e2dfbfe10959e487479b4f62446c4215a73e418f80cd46a037e354018277379f4e43097470286648b1714a11dca6ffbe3d1fd8174522b62aafaba572df042d0510d08142b7949f22c063acbbbbff6cb60e62f35ad80d6139e1ad5a37ce6a9420ca775ad4080bbc98f96cfed9be4453ee73088080465c2eebc09b8b4365675e8da66d6077848556f8cac20a3a24242ee3a45efec3242db7497b882132cc2d27cd1d2c86d2f64661d306d2a65498a3ff6076ee23ad79348530aaf84cec37be9bf2b7c5728282bd8446dbb08cf1fe49112557a182390dc1655e1ad02a4812df892885dc027b9adabb71adc1465b4f0203897642c06754a34f179e1012d8907c0aec832e62b050e3c039c129c1385faf5e364590a6b43985582632e8421530731839f17fe80b9446d183fe0e41b5c8745ac81e026ef87ae16f6e2f01237a4b8bdc11ccbabef8c1888b0d572d852960ef7c492617a711e6fa46d933bf844535e3a3e9ab56d812e3f2e786825b2fc7ec022d7db97f11da12ac1860fef5c8d54e7ee2789cb0a908bf5a5196cbf0fc1dfe797b77a9d111bbb6b4566843d0c8981b88a51bf05faa5a7272043da019168c91504f133246b7150ecba8694d1b6c63ec4a7bc7048a815ebf1d4da5efe134b8f0ab36b287753ceed6bd8b89d66923194714d21a1d7da260bfee134759820462caa1efbc3cf02019a8e9e0c1282962fdf14e83f54120df0c9b93d0de14fd13ab19925935616eb177be4606065d5b24a89708df8c726a76506697dfebd88011cd88f48123f3f1341a4c5b822aaf84be6d60373e991a1479565ec0b036b17f90fb0dec5cec8952d8c01e83aba835cf387c277133ab5ef036ddc3e633ad4ea537f92f7ceeb47671d750f8c600116920f5775ca4caadd0272dfef129ed7ff4b9330a689e928c0b27ef22e930d2bb7da68db441f02f1154d85dc9545b0527253e1165cb8e3c7d7756be0ae222e2813c3ab689900ab0c4fd82eccfa7901f5a107742264fcdfd83a9348b4831af273fa692924e29fd88c40233ccf3d96178433d9172409f44042fecc4b9e686bf693099f9d82bd130cc51e6a6f4cebf61038d577d27091086697b70379ff58dab4049dcc9af77f5563b1862c96f85dc5e1b8b803240ff3ccee0c42a2914cfcb872f346284c2da759ec3e3d302e31885de419720073057a72eade2007bbe4faf8bba186c9882228abe1b7032d0e1c7ebd6cb65f94b1aa78c459475c6d935b18316758b7f18dac72aa029a192b267badf4ec8e59b90aed024efdd9501ac148411ceae3d410af97905123643f3064df8ed1edc603d781648aabae122fbfb20d6e98af81de4a0b35568f45feff1b11c6e9fc652c6fe2ff60415923e10cbe6119114666fe606155eb4aa5ef9921b3c761b1d2bfbf67fab5798b1995c2c1dffe69a3692be0fdabf9daea5baceeb0cfe76fe840b0026290e86e0d82409f5eb09b07dd88d11052f3b04457a96e4e95835a2d080f320295e0dc4802f2de4482830a836e1d03ca3e734edfa8f973b0d1675c0cf9f4aaaf2bf28018b60162c3cc527c3c27a02111721c7373cb33083f480232e113a2a1a5ad2f457a2afe3e4e3e3b91c5dee58214ad0aa3a08272ff4dc33d663fbb8538aabe219ca921337e30b16f000a2cf7e69df7e09c72473b5f77ec6377fe8240369a51a529d7a72dffb49237e93e24947e763e1c0cd25572df2fd9dd22cd1763a1979edb666b2e6e3aeb1d5adcddc5cf82ad6eeac831e55d5b15e359c4fcbf529ec526d1754012636698ea8f0aed9262a3f75dda1ad2dacf50f62a9c89c75d32bc7c0d6148d4e14d6848b18b46c5ad27b86f0323e4fff36cd4394b0daf7eadf8c6145c6c39e26d03bcfa57e51392266c3c2494be8749dc810f4692660bcc3ce2addad7a061f1f651a301a425e89d5e5f173e531e321c3df62325ddde62d8b16a0dea7db4294a16874727df703d0ec26e3fc54fb354bd5fd044ccef8bbcdaccba624c58377579ae006b481f5dc78628aa95f39bb6b75685204b2200aeac968357a4329f7634f4f2ac9f40bf1e664a3f2b573797d40528561336bcec76af300a8939e75808239715c85bb1c02fcebaadac6e4908b13b9e5584570c9e4614803b1692bb28217d7a0a5032f276db2fda02c2200dc813f5f7b8322810b13752b55b22d6f4f8f192881397687dbb3d2c279749b2f185e69ee1159a458e4c7b7b93c48801435b83c1caa460455f59a060b3ba4641191acd1275a621692930a79eadee223c163ba02777b9cf3feedd7f29fcc0f9138186f27aee905ccdfa3a621a6896b14bb392c13a520c97a0fe5e1be2c34ceef95c98a20310f4c72d0301cf5c3d453b5c4fdcd3fd5b10443cd38c4242e6ee38f5be02338990f0911a40954f08b578b77dc1d2d57dea3305ba100afcd979ef66f3f9d4a1691fb8677bfc5694f1ffaeb517e348e814e94e9c1d7115f9100aad50ca70a5ef3a0e455675167846d878669d315cdb6e67129a5c6c25fab39668541f1988c701477664fa785449ec98737adac675caaeadf58ca61537af90a1450ca12b90001c3cb3a5cb041b3d2faf4bceaeda3f46fe5e22759670480888dba7c10016d62658a5ff1006162c012a8fa99d7a73499e2cc596fc8b0ac4715ffab7efffe47cc19a80c9efdb1d79004005b0696da15427891727b58fcf58aaa4d50d684294405634e191ab62d21f4eb4fa14c401ddc4698ca82816135e35d1548c82b3535e219e4cc36843ab7c2d62a58ab1ec08d36c34ca4cb06f68f5a1ae273e8d9d1c71725e219c56eeaa4957cb55a651f4d88ec75a9d3f8257d16676bd38ad40925b94c21e98c91527448f57c7688a48a1643f2687a320c260111e1f46f611683add3b301afe048cf26262c40310950962e0cd9fa30104be7c75fde1e134eef1e73afd2338020d191938371b98bac44ed7cfd64a0f1ca4b21c849bb539b211d3c5c4a5229420657a1b5ac08d40e44a8126c8737c5f7e9a0be739e38a789729bba0dc128d82bf30385531cc6aca648e5a5b907e5c4cfa253f25060d72f5619e2d6c0900a8bd0d42fd26b042ea776b8933c1a0b0d1e4dcd974759c84f6395eb09dd7121d75f00bdccc995ce4be0c1574122401f5142f695db3552bd30332c628d0eafb75e641c948a36f83b448d443c2837718eab97c4a9e4c0a917b01f00a60e15221dab94f0c0560cd7a9e1fcd21fb098311350a37411d60823e7faa8ac0a9542c3437a6da942d30289cf48960de4039e8e06bff74be10290d1b89c34a6e3bd88890551c0ecaff0c359b19a4521a819e3151b733e7a1bcf0d4afb197cb65142124d7c13c3a60ab77f009917443c7228bf4deb1013fa3c26d7fbad031688673da44d8ce352469e735bec6139bf266bcc1adcf4d3598855605075ca68b34e93bb723b919942740ce429275eb2d2833abadf93b8871c47f48469ecb557f90f6210893759738f559649eb7fd700d7f2ed91a17c2dfba2c77bc34a3d390e5d03a28cc4db903017ec97a220ba6814cb09050828f1a786841e362303c4e7292a07a428a8ea3758f7423bc0427bbf7213446728f2cc724d92a23e045b74dd7520dfe676204e950346ffd1ba7392a706a28e0d8ac47a0f7c85c47ac315109b2a807850c9d311a7dc01e0ada6a35c91aa45fd1c9bc8a7220cb615417d87e21dc9565ff94b30242e5505b444c2265ccb2185bb599b44e4fa27b887f1c3a955eca70580084b032dd6f6525fd1af9db5b794363cddd40b2ff19eac926668ef01d5fd56f1dada1c8b8df0433619f6f3eacdab1178b9a6e8038c0608a597eed9cd004580af2b411e18162890cd6415feaace3f62e6f303649d7e12aebea6c3ff7f80d8b1145eaa7c95b039d0d7927b2c72faa303fcb38cd9cdf3c6c4557ee5828d12b2dd95e697ff48cd74e69f5a668befb23fef4fb6defd8faceba701317bf483ff813b39dcd1afd87cfd234ff20d34651a346055fed15c8ab15ed4d72a674362157e6f970f35c1309afcfc1d140a4a11aa1c245e4389554733f3f11bb7f5608cf6ded217a9e1427c9afc84fd119ef73579da73605dd1500a7708862b8b37e3ca97b096db898661fdca5aaacb09dd8ea35a23a2ddee231e512ef93a1d79f20b8ea8b66855647ce4a81502d2e7454dd49cba36ed6eba6992c44d6f64feb2629f02c3652d89fc20360274a30737b22e0c47a35c203c9627bea4af0bd1fb853ee08dc3d1508904cea320b2477dd482c5befea03a5de9fe0712c57e64746d9bd351a690df985dfd8260df225d2b78ed149983076e800311e0eba56442fc0eecd91d6f96756a4004f6533f4686901e2ed86e84cef5335971d94084f0ca85806b11fbd13f2c5eacb7b4e2230984a3457aa4cacac4b326144d5812b4d4ef839ee509feebf6cc4ba00d2dd4405423ca396418da2f73ebee23c087e6908242742316f950f613af4ad5305478d9b817817ac5c95832c31daa352ed76633b1fe3b0ee23326b04cc6c44868ea049f60c8fe0b06c22973e62f65394f3c64261be434f7a04cdf77e04dae7490de265fd465114ab86bcb1849e62eaee6bd4def2bd6f78e7e8964d99469f01788e4ebb3c354660e5e801a5049eb22b1a9fcb22eaf54d2cd20c89c072b9cf4867963165f5ccee9f95089260c2c4392670f3b2a458a0c717428f6d8d398144d24c1baa1a424e61b19ac3a97e9d0debbcd26f82a8a383958de96142436e82e9cb1564fd6143d208e2078303f64816d1b6aa8b2c675e705e56e646c52a9580ac011bf97e49baf1bbde4c51da04c6f773bf08d55fee9397130b2fb48c4118111fa6a405827935d25300a58a25bfc12bcf6b2e99f22cb6b7e0ac6a30b7fe930e3cb7146f44493f671c61f7b6c2ac3a8caabcd84e847a252e2861bfe1a78b501e3cc69f44a985fdc57fd56f1aa0fa3468c750b812232b241301f4cc959796a7a69e0290089a2020391518aee7e9e9a49fce90108d5f7474dbd28cf939b6fd8c4f3bb082e8dbb43e6d27e98d915b5f22b13b17fa46fdfdd48f6f09fc08337dd68fd26293fc567f5576eaf2e873ca6ed3db22bf84fd4ca1f42469915fd395e6ccd59d0853ad2a7a92d7dd03820cbf8e17c60be6f7a9db34b670c2cee6fb464a9216f910b16c4548f0a05206444d7c1bb739783ff2a9f731aa83ffe0dfffca8dd40d9eb13500c3e512770451afa009b6677d99c08812b4ca177cf7cd9e06d6fe4784455f20761935499a97bdd543cc4aaf640ca60b8fae7b0638bc3312ad6ab6accd3d849c9188700becd2535bd7441a0de5e75043c2df37962a53fe69eae3fc2a326c55c5837a2d27d2a9e064964828674b615174321c801cbd70c66be97241086c865b8945cc43f18e0dd864e9d4c2559dd249d2c947ab2c3cd7cf1e29c4ee181743552eaa8948eb626fbba3acb5e94099d983f6bc090b4589247ce475ac7f4b5a163236b38936f511aa4571744fe51c2e5e4f832a93dae9a0292956269d2ba8da72c6972015b47b5b3f09eee1a0699cdfb69d5ffaff2066fb68d82401ee2db13a5b0a260d548061f6000c45687331883e1f356618e8d5e0db4c1609bf489576bd5f002aabd828f6d194f0a3d6242e9d347ccd452b158384df1a623c23b0de9938d2d4a8bd3d4c01e4ce47ac480b7521f86ba23106e7ca578aa04fc7c20904545d14389fe86841c036ac731aef9af24df43ba0b648f5011bc7e79a5aac149f850caf9436874eceb4a95d1b0ae40c71d71b96335474c1209b2b91fec2d5bd6ad4ba97e401f693ae12183198ad1123532296848a7021d5016cf6873215af201b55d29d24e8b76b95d64d245522994a9e2a2066b928a4299e7e032d76498bb22b9f0db5506c6e1479f8484b8ee536f954bf0d84bea0f6a01e1d634d58ceadc15e0189e001bf2a09c3aae800a9f78d76340abb3e480eadb375d3a4f1be1ab72d2c24fdda0b8765b808e66d2867de3383e1bd1dd02da9ae4580457b620c51b0cf5ae31d462ea6019ff61a3bfcf491b0de5d7a8220a5d46b2ef2e53bd04a333a40b45c824943cfd45b0497ff214556dab7806b644102000ef1f0176aed3d4ef26a4544491906fbe4d9cff99cc6ca2a9e7f3c1b777a791a30a2036fa2f03848acf29b1082dc9c112f6e02758db14f1f6ada5c625374644394d17327b7bdb62807cfb01b21e922abda6533c782d61f1ce7b8fa8302610358932078b11a90bf4274636980723ea6c82d83bb1cc2a3ac172105f6976c956033b916d25c90ca42270808eb4fe0ae59623d0f73d44c29ab04d33b88c8f547a6d44c46817b5912c5aa3bbf2626614a70922d3aa0b2b74bf1e9aeb8b8d54d571b4a0652a9332eec1a9387960addda804066c9a9642734ccfe4eff4e1bc72479196a1caaa48bd206d854eb35406f0d6a4c440c4f8cfde3ea3ff529d0bb3e0c398f3fcf72fa32ca9b61abdd669b049d139e18e30fe45e579bb72aacb9f1793f2a122fe46044b0a578420d17349602df4e02bcae31b5d6ae075249141e4b90ab018b23ea60abb07b45c265b1e01b46e4262c1e1a78ce142f7e5b78f78a0e44ac621b6bcf8b10712139fd5a3aef02dc086188a624d364dc158cdb6512fb5c6e21aa2a0516876742dccd40fde019328b90c521877e9b2101f8428fab44bae02ad0186c8c3aa34b44040aba3ec384ce5a37de7c4ecf3f9b7f0900a6db69fe309a40d4ede97cae977f1cbb721cc6e03763527ba360687315626b63da6b45ab91770f1905c2812c8465f0daffa97e865f1517953499a4cde58be8937a9dee212e30867dc744dc09644ff191da27d3ac456228dcf2464c9a25c93e7f8f71ca20ca004441612c909d82b6f6ad9ee28edecd39b919722b8b35c2288a79fcfb8038936a16ee11435ce8a156a866324639872baedac56bc8386675270520c3f956ca6c415b863165e0de77e1eae6b9428526c52cd03b32ca98d9097e46dbe539ab433fcbc43c9e21c1bd918fc52dd3efabe45ef2b7c28aec3e9c260cd7d8fcc083b2cfda5358ef72fbca4f0157f406d8e00981aed4a26687e6760e8097ca7a89b48856500c6971f2e2d711e7295d68b22a5d2d2e5d013ec9c01179bc12b4dc2a73286d877692d10c90e1e597c3b2d85e7e2f2a0eee1aa6604f5de913e0d59266d7a5ee74efd6ad82bbb29f489f0e8644dc375597d0c6bf4484ebeddaa30b18636d15d866c467baff8392759cfe554c92acc264a4fb0223a202ec4ec7209f2f02c2297c0d0b9f6f57ce0c1f2467f9e98855f2f7214b6bdcd53b1caf613b35c706153039727da5ab72695335b8fc6993b305c8aa1a005540ad5ce205800881bf4dd93ede279c806cfd7f50b33278fd4b6223a86b55d9778fcc1907ddcc31c44aadec7498fe07d4ca57a6f8e0140bf51f705c32c5c41a5d6cd83b9e3bfd352ce941bf1e488f0ac49229fb15f721d751230ace6d7c5f1a256e222ce192fca8b0b13e929d4f75d7438be748142bb768ec056e3f54a92d7a05ecf8043058f9e8964f940a565e134e580fb4166403b16b442380c59c1d4611791ebc14b586a761007db2ddab172095f783b9a12a0a09dbdf4a779ea3271b809fc24f998be2677f2133fe2b982cf3b2187d34f03cd676ad8bf4fd456e755e7f347659cb44e2e189aa5a1213a68df5db5cd3fc37d84ae18bf0e15787ea8b7a6d4986eab3ab0f258cb6d71674088775b6b38533790ef8cc8f7e868a187880fae5e33f385de01017e227a5760b80bbf45a5500cc72a7c091482b4c2a5d956f3a443c8050183b51f758542040e04dd1c46f354ec635c20ef76729b5cff19089b84b23e2daac27a4f364b82ee72f2b2b9c5f978dd6805d75af043eeacecd9e50e6beb6aa91410bbae45bde800c86ac3ddcdd4d5985f7567135c7cf5e8c9db8227530a6cfaff86076f25dd80580af1e4cc2881fd5af7f0f59b9fa933f6df5f5483e28a4b0f08d4577130b4a89914ca0f9523a0920ab09627d104806a6bfd1808fb3644e9db6a4e8c1512d5c816842e190076ee432e1f2e90270dd6a9d4fe88da8b5f0da9e92ec153e3c5e840504d1698b115ed803df86fc3991c919f8e0e819d93d271bdba907e7e2abb3cbeb46abe4145309bfc4733949e38617cd1907aa50d72c53b5dd20a113a5a3568842b677c29b0c7eecd99914a19fad43fec03e609d5b149b1bf9f3762de88758e9881483463ee18b1a5f356bfa786d4f8a654dfcde454677133979ae969186f7ebae599362156115bcca50981c8f7bbbcabe54eda5bcc509199246cbb34d0a651357bfce0b3d5a64a6ed74bb940c5068682fe361271c4d4c0170bd34c351021310be667c7fb757083a6d06cfaf6064c0bdefebae5f0fe16184b6e9d280e3c47bd0a324397a62fafeaa4eccb4b5675d072b7ce0151165ee33dd616114dbb8cf7b34febf355da7ea85d2e7259c794eaa65582ef446616cebc252c80f4a3fbbf29fc0cacdaa5b852520069a438b0052dd0ceb06af1459b552c3b9028d8721e572abc3b70216ecde963f3029ad184d75cf64eb5c1bb784a133835f8e78959fb3c7d681d98af30957ad43550864569db97eb70e05c0a4d6cb138a27dfd3b21b1f73854863cbf447aac98c9dcdd4d997b53259a0b69a1e9c3c6338fbc8ce19fa04097d64dfada6d7c55c30eefb05463a6c8b0c18a718ca8b04883888dc6f43a1375b4e0e36202396b0b82325cb96bb6e7f575f9b77303299da10b1c7fb41c85ec94833619a6574fdfc542dfc908d4e8234962707f3f4ece71b797c1a24ba254211008cd87b64b4df2418dbdd69dee543dfbb4c3247958f33599b1d71900f49a2027987a8d74a404fdbd14c9413d8db972002eb4a0d56fa527948b7dcfbae74fbeb4690e44dd3c5a386d264c80270726d64ea2e7d0a5565e7d32e4a0daca6f0d8830c4cbc1824bb3867078799c74876d125d114e364a2a6d71835398c0af905644478bbdf8c4d3aea3b8af88c50c4f3ec531cbac7fde8ea930e8856588eb3185fdc8262a198a784f000bc6fc475dd0832097b5e61f4bf7c4c86acdff3b18b7754fb650053341dd83765e9c471077239d81433d53a410073efb23ebad5ec3b93289d9c341dcf4478d07a18a89f72ed6eaded133a71bd7e8a37f9202b2e5f1743b24798068b9ee32f48611046133db420c32d870f675d5e6d1073b8bb673da5c8e8d3507e31d3f89b92e99d60b8bfbb061a8cd681544fff6d77498f772f99650403c8a0ed5797f2685218bf5f131f1fb8145e92ad79fd7fcc52624bd7409cb054414ab25322d428527b026802ba933c8e4aed5734052a853ffe3443edc5fe23d1d170da3ae5f883edd302d458d45af2c87a790720a2b048605d2db6b422c909ae11c7514b8445dd8d9374565062e39dde4a472951d7677c598b30c3edc2efb48c668514acb9044cee7b746572db3631bf948b6f7f5c391a574a7ffad5ecc4ca458b8a7f15ad86c797f53618871ba8a8a413c6a5399512af5c7b934ffc7255e143c571b668c16d72fa16046936e1eb37d61244f124219b1f2394a250524f05968c170c5694ab63612b5073498ed66a1058b427260ac5a6d027aac7ebe0106feee915a089d9abfd49a0abd683ea15972dc7b32f3d9859f50114d68945fb5d0b742f20a3a5c58b66ff3a86440899b8be3ed27d074f6353001ee11c743f266f45d7418af760ca7bdd237524ae7ffa95dc2295ba5ca2ee37cfd84bb801f97c20c48e555fa6a7893cb5563e5b3f48aaf897876c729bde445d4b4896c94a5b3e0bf8ea7dc9c2cf05bad9c91fe41ba80c01ae4ebbd5aa0dd40836e13bc21677c83f4e9343e83a61160ffb1b241e29f274bc1f108e786b0bf02cfb3884d8225b314ac872e16197f7524bcd170dee60901d8133506a09d3f17e7ee91bbd76c4d7907c2c5b35e12504946be2f786137f84f64c3b8c3f2efe09ffa58d79fcd245fb9b55f9c82325548c50f34b77525ce6ae258279296b5f52d0d096e2ce6ee627e767926ac192d05a447c525898cf3ddab2ac0fbcfa64e9645253e8cc20620836743dc732419367839ecf052d9b4ba0455c93c49b9658817326f566474b0907232f98c03c987cb48c88f71847f08c3eff6d2cc184dabb085412a121d019dfbdafee94a371949665a0a311d724fcc397b4a8b9a45ea50a18e7d9998e3088621131e8447c591986fb143416e86e73d39220007be111fea04967b932b83123525d4b3bc9ca8548ec029302172e0e8f4186173901ef018cede9e58df4d2269a586b4e8bda401af681d850b6e551936f4bce9ea04ed946ab77abbb78067954eccaab0980a90452bae47909c22271ac3a9cf357afdbfdf8808bbb19f649f777c6497e5ae8c1a53a707284093fd7ebb800123b3bc2eba217f46e3f197444f23993d732647a9367129fbaa8d8b0f0c362c6682f77b405f2323e190e634926c799946ae44c1e134ca6c621ec171adb31e21064d1142523ef34fed1b5719b77384c8a06130f9273b6ff03ddbed260a49f015dcd06f200cdceef672fcfc924b494c4732fd350796836c75ca33d67f6e188556019a2d78456d30b8da6151a5da3418ba894477b9d49763c67fd1a2af31cd2331f5c3a4c698419508b90b4de8da029e4856eb33a60736cd3fd4e231f3919e92b745fd6269557d6f9fd8b9c1dca7ec279131d25383f13416f408b14c0c20ecb5455f072aa93c8ba83e3ac8d55d516492da2cc6312c80b21bdb6e178d3113395575e45ef63577b9accaf419adb886b2bac3a7f4b30c4d24a8740bc1cb6fce375a5e1872ac5afd8c7642b4f2b97a3601377a7a81dd56133907762d93426b3e5c9f4dd668c23cf115a05017615656fef5e7212e7479e31e816d44b85cdaa0ee260c4643307b56d8c9108a18eca45a152b4a00d62289457153a10311045550f626e75f123d0ba2cb745c6808b13bb96040059758f1df4d85732c58bf9017a13403537ae23314a9e72e6bbf9009f94f5d8cf5c7c5f2531f224e6e772f1680c6ea20b1df13f350996eb29394ed5d90c44f26a776e31a846ca90d679c442ec2116554b82e16452d6f5e2e871b44b1add82f2476736b40628eb1daba0d8da9c4ac4fc2c738a5aebf8c644d908040948ea28b517b6ea62f8c34bd1bb7261dc43f0d7afa13d2e2fd6f53548358867d9809f0833474b74128c028e84593aeb5c4931282fa81a6dd162d466f4294c244e15cc1ceca17639f02d928dd3a7d92396fb492b7a62fb447bcf39b26426e5a91091e10ee8e38d926d842506da0402f1288c843cc94955c15a8a7499008f0a996ba4634e1c2e4f93a562488fca9c6a9360fc496d8487c90035b4c1f1c9756e1503b68fd6655891e5671e494cf496ea440a9674178d6264af6775be2bfa1cfd201cd82c0f001abac73e5dc1ac6eba85c15046c3a7553b301e15245cbb5d3eaa97d947aa27cf723c7cd01a304f058653af7da4277af90206c656c3f99d53fadc708dd7e5444eaf7e47eb0c7fe4f9979b8717ad874e187302fc24d40a764bda9c9e902ed260586a2deef43c0d3c40e4c7753ca713894b23f50a960ef6a8a7e38165f6857ab8a255e5a64d00b4dd0b40cb49c02ff7efd43afa9b2f585e10ae4fcb3e1b71040c7f15abf570ed84d72ab4ad1d73fbb476ebdf2e006952f17c1d30b5e3df408ca2f1f6c3c7187c330be14634ef42b28f720a9d2693a46e67f14dc7e093dbbe628e0933b6dc2c7030d9af428b3eb60ad1ed6bbb68c45aab58fc8aa86fc509f4f6e6ca425f5fd31a85705c4ad6362b502501442cb79caac05516dc3aec5ef1f6eea774c97b48a32e09ec1b7f841a2eaa53fd2bebbef41ee58beafde876aeb9c9075bdc47d3f00f57dd41bdf4a3e29ac18999085031717f7c5bf2e4ce871f9d7d2a98bd9df019bcb73781a1e4fddbf7aca61ff47ec7c87874053506080b8bd3666b45d416607df03f3ff4d08fb289c3b0c6ed6b18529b56caea6aee54d279ae88bf74c9b6b2f6c764c4ac275a8c38a7b08a856d880e3a98614c19d7ef39b64f4fcfb1a4027e335333e6400e5c209c13c443a27253247f68333b4062cad3a06c36cd3e3b3f5ee9f4b9908b82ac3c0268c0f79a101430ebd75560629ec70bc7c50d0952e930f0212d082ddca5fd8b849ba6f69d4c8a278647579c608628e3719ca8001bb75c95040dd958b69122dcd417644e0a59881538afd99da0bd4298ff8f67a9c160c629c8d3d9a1d59ab8d78d03b62ddff710133fc395e8b7aae0082012b01062be30622fcd6d30c4a447dbe53d834f05a80262993fe8060a5092b535afe9bc12c6d3eb5c496ca94b4e284eb2c30b2cd877c119c1d934e977bb3227391cd4c2d0786c2b08de6686e145b76aef12255ef0783d899f5de2016c12e076d5f6ff8cf8c0d8e0c10f300e43c22d617c915f1e28eeeb29b6b9cabd3094aa1809e9ec5df21f5464b02e98b09e2a75a59f1c27ab986d6db5b7dad42863727fb4e0c069286fa59e8e74b333215965c283d51df0daa868165403e1ce51df3165869de528706d72f992da73c93a820b6ac00ead5e6bb34bb13a0b2d0b6e95cb56891ff0addcb597913612fcea5fc8c66e714865484a6cfb984ba78c67537457028dd6b511d946c1b453507aa61774140828578c715211fea370fe7f98a80e0517274c7763ca96e9a1a8629686ecd623feaef39040200bcbeec0bdb9c7d1ddbd88f726cd79fa0d631b18148f8db10b7feb03bd27a93ba609b62a0cccdc46526eb8cce86ebb0fd48606139215fd44ba4d863981ede66062c4ea61a890ee12f66d9dd75254bd24305d75f446a8d9cb1c0f7beb5730916f8b2319af20b171c25a4e12c2cdafdbf786b171f557ffab3446865da0b7ff995abddd81024a294722d3d8bc4593771a5b14b862356774a6e683d115fa55511215918222242a02604db4661ebd2c4a13d5a74d86a4e8f36e51f9bc8333dc54dfad64c2809c65851aadf7ac610e6421c72f4ce5da05a408315994a79a60aa6da8f74c431959dca39e010892670e2c2700d189f5487e5a790b935f89b751db0c4c30e0f615ea871fc993e6a5842f3bb10961b16c8f773a87b8c7e64dac61c49f67c21742d4e54fc187c620f09458a0533b9e97dea0c04603e4241fbb2013eae54cefd9e49d64af380bda9b0a39a66ad350dce45038d156a492e2f3997037f1f4e03d63cb630c6cae2a872852453f8fa6266a0b3240499d4e7ab96a0c2ebdb31e7fc2f5c79fe3b38ec303710428189a45f60745591a39ca008d5bfe91ba19fcac6fc6296fc453a66d7253dc59d8a9192e1fa2d2398d16fe9ff0bba96eeb2a31e5d2a2f83b0d7eb479f5bd7a66d6f1bdd1db9cbba4f0b540ad048a989c2cab06cf58e453ed30bbbbb46fac5f7df0f3d3d1c56d9351b3c8f09f46e9b5147c13dc00d590c5dce72a5435ace3afb9b8bb3e57f602ccc2e9320441bd9f93e50cc00f1d745aae87a138fb2f697cd50344ed6340320972f1513322128e20c732da0b3edb42e7bcbd4755a70552ba06ebfe23c80967654ad8f3876a8b05d3138ece8d9492d58805e7d7b39506d09570b727fb9d746392ff3ba0657d44484674d2ea6b132e17af7e1571b3596ad00931eb7543284ef5181aabbafb8a1bb0ed46dccef053c63ba75d6beea92e8c6ccfe91c0a9587dd8adf745bf8f7c15e5f68ef030c76e08f242bbd48daad06b672cbdba45cf056f29643cf7799a30fa321a508b414dca4bff075a82efcd80e7b9d892d27ba5d5b25bce5d04a43d4d8727701413993c559d5faea0ee3fe4c8e197e9171faddb5ea856b2407bf0872d4ed1581a115db756f1e8ad4f5de4e47fd9add689955a2b663c6a7c865a01d4f869f59af76d589a158f9f6ce8e5db52d49b4f5580445cf50a7b9152d896878051272c0dc76db6f2ff27e020897ceda3c5de69d7cfc17045a725fbc5a304eada20eb83eba1de77ee843b1d486ea41433c0e549436aea9fa15688583c805786c31c06ca4436ab419242d0f2035a180820a23c4781edf9493a5f90d9833cdb38176743615c1c4490f066865a0b37509d94de4de52cab465d90a4b0ba00c2848ecf00dc5e93f3e5e7a8f8d07e6a98d87c1db9d9b37ce7a78d99cbcf5d3bc1501ed70f073691b41de56c03715d8518c6039d8863d49ad8b60757504abcb1db0bab4da5bb72d612d9ce7ceeb9a79ffda44abeacf9a4b8d702d02d7db491fef8bc48ebf3e008311d680eb8ded1d47af5f610fb83e52607cd95bddf024f0d863ceba81777bb5166b05e1dd9d439d579faafc6b07a5d73fabb5189f3bb6ba631b61365bd4b897f3fcd5fe4a8dacb5d9188db327540fa4db163503d25dde36572eb3ed746beba406368eb4796973b9e9ba35d278dad01b2ff5f1f5e2f1d7d9d9cfebaeec9dbd4fcf9e535bf6f80bc8dbd73e5efbda87befce2b0bc4823f26c1188b64be379bbdd6ef976ab413692d7bef695203cc84ba15bedd64939e846bb9da78f8fd8791f37cfd7ebe53daf93760e4f07d1a79fe7799ee7799ee7abe775f29c670fea733a8fd34ed3344dd3344dd3344dd334cd0aa3c08f9090d049f4426df6247a659b996f2689473db027d1abcdb38139ccd45fde48a98d24c1f575cec7c9e0181c973a576764ca396d98f37066599e3498032a061b5ed976e249ad277b7da566407a99e54930df584f3a6a23fdb4153b8938f4f639a56330689f746b74bbad78d27393ee63edc0168d19905eba7cc4cec76cf553b3acc43ad4d516d1c1978e808afb40f39416f3b2ec2fcb32e7f22c4b73fcf6916e8b465adaffb3c10123385a2a8e737e4f9d6514ac21ac6a88be483318057a6c6d8b4e6b6497ac521208a4327d966799e7354c49da677976ee2ebb86005eb01d5b09c6cfe752e36a903da3913a278bb9b5f6c771af466a1ce973d2b245edd3ba4aad78b60ae63c113649eaa45ba3d68dbde6403a993acf2ee95cc79c679190e34f899694223d59db3de8f455b45a62b22a064f10608774777795ae9c73ce39e7ec72b9dc74e59c73cef9f49c73ce39bbbc060bc1956fce668fe9a79f1906c2a9c1f4699bb545b6a868ec8d452ee78d2a3e084681eced40b008640f8245207b7be9b339a7298d160c9a36c693a7699d08e68013cde0f569f586e5f204ea2fcfb0b1d72bcdb22ccbd12cd15bed04d7ebf8256dfc31784b73dac1dbe15553d23bc01e80c15fa07164bdd55a6fbdd4e1b583da72079b4ddbab1c4ba81e481f4bd40c48ebee344f4f10aefeb50fb5160816422ecfb2749d68e9286a6df9f2f082d9f08ecdf2dad7d647ec3c889c73c67df0266d51698f74b6088488ce5d2fdd830f3a677a598e5f96650e82859045b875f9ccc29ca431f7d8b5a7ed9e3e62e74fc7a68fd9344d7f99d6da2a118dfbe0b81436bee9335808a64daddde080111c2d15c739bfa7ce320a5ad9ad8b5443f4e3d3c6e33f962ae5ed8c416b0be2dc69b4340d56a53cabf5a4f37a8b8cf33f3eb00894de5a9dcb4e6ed510b008942e77dd78316f6f9fcd394d69345b8ec160700ca675c7066b92da226bf42a51f436e6beba2a1481cb722c5a3125f2eaf0a77d9d7f5221da061c8c2ae5b5af1c971ae7b00b1b83c2b47db6a8675492d7bef631a0bfdcf0e6ad7682fba58fd8f9f206bbc5ca6640ccdb51589af6fcdc86c42256c790f403f84a1566eb2dac013e3014d6deb39b09c6ef91d96ae33838c757cfed02a68d07e2fbc6ab584259558bc40d88f98f97b006fc78efeca0a6f9729ed3f4113b6fde6af5f08251a0c75fb713b4fbf809a34076f37682b116811f8f79ec2682d24d307ef69f9b087c7a787a6ce995f4b6c1777e4aab685622b4bf720bd16a015e3b16d6bec691fe426a0e24e9bc3a44f24b2094c84e82bd6c3d54a99f260c84d3cfdcb8eba6eddadb63c568797b3d8d823767cd09df9c78d35f443c11358b8695168144da079e4f590209f1d40eac993183f22d504b38664063d2b215f7720db6b29e15f772221b09c6cfe0e523d3abaa5ffef206b8069bf9f2a1216c0e995ac2aba22f7b5abcd3e94befc1e7b57e71df20bf36eca3c541403d416e610fc0e0817c44a2c1561b577393a93766507a69cd3c116c64fa8d4ce8cbcb9f969696d6c83422a91e4a0fb2d56ebcf1e9ec8d1d8c496a06a513dd867a6ef636562da91e4a206f408fe39e20b7b65128e4d8d67e6d7d1b99849e806ebc1e9963180831c764252d4aeb5cd650231a12eab18dc7170c665fc876b6a91e4a07b269699d6e6a06a5c3a91e84332fd3344d619ea6699abadd4ad334d5e0699aa669cdd3344d53224fd3344d873c4dd33415f2344dd3b4c7d3344d53eb699aa6699aa6699aa6699aa6699aa6699aa6a8a7699aa6699a6e4853200ff2d4673010d29d33759e5ba79c67c775faa4af3ce503cbe9a961ca079653b3369535d45217d154d6504bf3d0548d281d2a85a66a44e910d933950e09f5603b950e09f5dc29a11e6ba7847a6c4ff558d4d63d763c4f14c84b1808425ec24000f2b3e69a2d2a1b797ac7baee8969a44f09cbd9859a7de2170cdd79a54fcda1f4b2ec79dd3641afb6ddafd990be740b7cfde4532b8df165e91a6ce7900dc876a6b653d8b832486887426be69cfad2b36827d697e5d904cd970e1ba6bcf3f7eb9ccccb98972fde0f4c2a4dbdc7adf3ce5feb6e0612f13891db39adbbf9778d7e319e68c789dc165b773316915b22b74badbb1949faf444a713b93d6a1dee590ea5671f915ba3ced1ccb40eff7e6d7e737e279ec8c789bc87adc39948e4fdd43998137927b50e67a5c75ac242f244de44debdd6913d221f897cbc6a1d99c1a4669ea89dc847a6d691998888cc484f84a5f4443e123909ad2b73dd227209b4aecc56e915918fa0731a9cc81dd03912904ee4b58520841f6842445e9bc871ad2b851b3a4782a19713f96d5d8965399424087222d7000381e836a657f8f75702e0daee4f6875e7ef27fc097f585677f6cedec5ea599d8985d5fb599d2914fe845667fe7ec22f1d63599dd9b31c4acf394d7b18ab67752e2cac1e560fabf7b33a9750f813fe84bf2f5dbf9ff027fc09bf7412cb969e739a92583dabcb58583dac1e56efcb2cb41c4acf394d85e5cf72283de734cda5f0cbdcbb3d1a2d4d7be586f2f69c87674788c186f366bb9d4e743bd31df4749e73e7243a775cb0d36fbd9db3879e2fac1d17d689553a8c760a775cc2532b2dfde563fe7e26cc65f64e9ad9f3317b66ce5830ac8c4584f5a5bbd052e80313662191f04bcf4dfeeceff7fbd24b8cf3ebe8cbd2c9d176b6894aeff3ac56c642b11a0b63d9c8abbe12a2c2166221797137b135d8faf36fe87573e34a1e9ef1c91c4bb4875eb3137dea17cc2b90ef4b1742fad26bbf2ffdfc799dbf9c7be7efa971a507d946bca0f740b7b3cd2f97af231a2dd5b2b053ab71a5c3a052b2f4b3d7b913a59f39a7a92d83fa5fb6d24b5e366dfdb64de7c6d79765e923b1f4d24724a8972ef7d981f9497b05f9497b5d5b637c1d0863da6d1be940372808a86baf7ad65ea30d93a49fb51769b33d0abf04baf1c627d2816c4d96b8c7eb973e22a921ea977e6a206d35c475921cabae9e1aaeed510346db69bd2fed892f5d66f4a5c78ebef49f185f8e60bef42eddf6f0dc78afd4c6f47396565ffa08f42f4700bc4618796d6391eaa164aa1e4acff7f54b6d09b4586f2f6dd9dd0e03d1b8da41f6711c470b0ba1dbde4034ae7b3cb2bf11f694f2f01146e168ec203b99739a92401e7f9e5a43ec380f5fa5cec35a9ef4cae32acfd246dac8a5c691a85f5be9b64497de75e3b9fc344bd08e6334ee028336679bc63ef63c7c642bfdec3efddada76f2d87838f8a49fa58d0c924b4fba9b361e0924017e12d83872c3c398a42ee79140924c5d14804500631855972b07d2d31ab41d4f029faca48ff491be663aef59be4a1046183e724ab1dbd12f90246b5699fde4e5275d45efbaf1ee5833682f3f94deb7b24fe78d67db4e9769de6e67bb5c5e7a2e6cc630352546858fc88a15368d8572d56050cddffb34e40847c31f8050e185cb921a2c4d57b2d0fc58b8f75ef349c890c3b5a7b5b60245e260a1c2450b8d3a67f06896c118e3d3348344c975fe4e61dbebf57abe7befbd469880499c90216202c63573efbdd775c3189bf7a2e88de772d932530ee625978bc0e5e6cdf45c5d373dcf186f9d4c5887a71f33dea678eb204478f081032420428fb77e811136d0812a6ffd039d33df7a08464002560ef6f649e9cc5b6f41e73af4cae4868a70bcf5d1a873f66d7d7241c75b1f6374ce577f49f509c8d5db9ae56d7d0ac2f0b652bd7d0a52e26d250a2b14d83df1d6954b714e9f5a401300134881362f442951c6451ca71dcc33ccd3220f2b1f06731c0c06732d2e0890fb28575d4d61e6d00a50b071422a6264029632f9d6281b3b5c23932b333710e3ebe5a9d6bf5ebe01675fb4d6e5a0d4141a56a0826aac400519be75219f31c1407899406b5aeb2af2c35524de6b4201a1e1c1c476b4768999b7e6cd2c622817de6c307dbe136351e929284bbfc0086559d6a8f165492c891b7056f7a1d7eb95b02bfd03080fb29e8756969e3d6de14bffe91cec4b3f8b5c34e23cc618932d7e8fbd9ac4ea637aebd717e7edd38c244d336670a221c415406b0754c14b077f65d8f87b657cf93ba4fd8febd756fa48c7a337c95807918296262a0043907091b442470b5a6fda0cc99c576805638c63ccf99b82952b17817361bcc855185250318c9e62103be0dbe3841f35b6d0d049111c63de7b2f8692d623185eb8c02f604879ebb41761deba100a47de56c1f8de2c9f7bef11357f31c6f896f7ba38c1c6dba8b7d69ef0e5adc55656258e97e14f8c6f4dd6ad5ede628cb12dad6d11e5afdfebe4e2c55f29ec1a2201e44b0a42e290b9524686181e1c55e386ab2c5b18411df57a3d15e5ebde7b31c6f896f7ae88225a1146012c7608597cc1a01a157d07464c9c5aa0288778a70891152ed0aeb516b5d6da7befb5d65abb42c6ec563125cc796243d5842a490c346b6d53d4db7befb5a5b52a963c2e3ec6175fd75d40119a2826c61c0992c20dc0bdfec1bdf7e2ebefefbad1d2d2665aa1885380142bfcf9d669429e42c85bdf9082cd5befd03905bcf50f41defa0626bc790bf5b6e8c8dba6b74573de322162e1997bef4501e631c61767a04e991c4b47623485b1d6628c71dea130a180bf9e5108fffaab731b527c27809485aac8529d188a604e6b6dd391b7f7de7b424c0d97bbab1b577e367e98a991cdbbc4cb5b9bf39727a4fc8dfdbdbe26f67a3d143bd2bba88fc074cecc0a818da55e182f563d303bd2c7adce8d5fe63ce97da273e6933e168958ef62125a1d07e004392164a9848fc88ef4f2a48fc4ced5aa15269e2cadce048e278aaa9c1765d28c99a13824b21bbb3ce9e38fcd93fea4a7c0ea4cdf0546e800e921e8dcd0934ec28e27dd049d439f341d6075e696e5303acdeacca20d38d23f581d766122496a889139437624161526e7932ea4a050021515574fbb910b9516af27fd6605e9adf5fc72b212f5f6c9db628cb7556f8b5842b801f49b446215396fdade34bf3c7d0e02ab047997cb9575195871eaed78d65dae5cbab2cff7a35379f265595a5d15e67ab0de5a73cbea72708bca8cc703788c3353e7723033b5d06af57acfb3d72c3acd22ab2b1bb882a3c3bca4bcacb3f96964cb4c9683bdd9db79746f67510d169d47cd25fd7df6599d49f4fd485c63b544ced2132e555b9ade586b2d6905c3cd5eeff57a26687674b272efbde494276fadbcb5e2d1935eb23a898d422172a65872055460a449530270cc142d3d152ac9957124a5f4f84b65fcf57abd15d6daf42ded012e54799366050d3a70763cbf7a1eeeb4d65a1a57dede7bafb5eda4cd9353493078d2d31fa7275e9eb47ad2090a91277d03ce8427bd43e710f0a47f0041143ee9223c8051a73ce9142586272bf19a3f2751f584b53e86588aa64811a15264b3584bbab5d6bef0f6de7bb1b5554070dfb9ea5465e549ffe95cadf2a493931f404ffa25c14306a9146a7ec450021b2c64133153ac30ad6c44f0aa9003138a29cdb08915214c36616d3dbe3dd92405275b821d617614297104486f00b0a89f8db15c22a9a2a0d8a16a55c6ca8699231367b670e0ba51484eb02d1853fd02903af1203e510059514b2ac4c97204ca78e55cc2e62cb2ba1c749c99b02d073d2f358e8947de32d32d071b37e62053e7aa0b37fb8229689aa45c81b1528597a2b7e620d4130ad64d62e3cca2759e493469a4a34ff5be006f16bb0e2d9965550231cb2f068a313b5e5afc50e5088aad16c533c21dcf9fb4f23cdc97cfdbe049ff400410567792a49351348a3c79e38da0161fdfcc62e346378958883fba6591f272b0e847e2d71aa276ae3a0da33ec45b6b9a1bb0fe0c9e442f184994196f4d79b590929002ab23c1ba075697edc53daf0a49b4e04578b1905ad2da1cd56ff5ea73760948f41e3b892518dfb66de3bda0449776c4f8d65e5cb34ee21b5b57c0b75babc1356858c0455194e8cfb35ad22dee276d639dc736de0b4a3cf68af11d317ead3611d49abd454001df7eab3d4001df0af8bed53a7fde57d7ee5a315a4990a32b294cd657aa30585ffd863036ae733bf3c79ea01f2d87d147abe3d0f4d64debf796717f8e6045c0b010f025afeb8ad0b9eb72b9ae795de6ad43e35c12d8706f1dae8fb0edf6629db022a9c538df9c6fdde0d97999975ed3793c9f2f36cd6b9aa6699e6debd038d35d3609346e746be3e4d179a5dfdbb87ee55d7aef889d1fab07d8ed123c72ac9cb4baf5dcb8ac3dc0da3a753edf7823ef3e99ad8cd3def407e63f3f0ea3394c0693fd90083e6ae355226c46b3c17cc7673698d78fc96e3cd88ec76c3c1241f407ffdc5650613a8a6c3958f376fa93d47a7bf5f11ee771eb34ab4bdd7a8f2ddbd26025def4e7961845715eabd380579d7cf5f62b42df6ad5e0c623a1dd036bf248785e892b87b2560ebc14a44fde9bcb5158bf8ea23dfbc90107bc16d403949e79a5e75bad1a943ec21a30ee7204c627f3932dc89e6f3f48bf2406240aeb285214b53954b77d7bc1bd79aae69ca6349ad7b6367bdbe004f75d24decdd0f7a6e8db2dd0f7ed65d6b7dbe277e924c9f4f5eb9f3bb0f6337db9362861bc17fc084b6121dc8cc242b0971cc7be6dd0389cdd7afb680b6182fbb57ab0cefb10822b84d2db4bb7366c82fb3604eb72d3b38dc7c3b33ede44f4c042b0de370f1a676b975f1be9d6f6238c021890e0f6c02870ddfa6dc487cedddb887183ceb5635713d0942dca63dc63573d47fcaab9d1b1a7230c04b2aca3672f4f9e17948a3f3cfee01ad1f54f9f178c2a1dff0035771dbbae1f80c1f74d04a4671f3dfbb5f9c67b49dd1e47bca12dec29bd5eab48f8f0178415ba6c79ccc0926075238d96330f477bdd78b4db2df3f9226dd947e0a804735bbe8d3f98d2f35ef9f57ae1923cf3a8f4d7b4b97eb924c79f0817dfdbdfd543f34673cc414e1f41e8ba03420f94b461b57ae82aa5836fa009fddcd3be4ac727895da4e9a4adf4b3341b9fb6f256e2d35d6e6d76d76966376dd75d99bc89003bbe9de08cd2ed5c8057873183f6ea15dbca8ac36e6d67c56117daa91db0bfbab1f3ee1def883f7cf87b47d34b3faf77f6f2f4eb4d02cc7bdd789d5d2ed3747969ba4acf364cb6df0f59a8c2207dfa6a9ced71cc30a8b4362e57a215e183a5d16e1dc1ebdbab97b36e1840f9d3016ecc80741eced67b1c6db6e272e5909d745c76323bcf9fcccea3ed64dc939dcb39e7256903c6937c75c05e73ed18e310c6113bcee3ed35fac6184d29af7bddb339a769efd5ddb82c2db6f5946ecb3177ffc829413c12c1e78da0123f671fd1ce4bc1df703eb711b5ceaf60ba8f8f8f8f8fcf6d04e97df31b94b4fa75583d61ae0cbbd5da81e7ba95f936a21de6d95d36988de7ca5f612396a516a83b99a78ecafc4cd3ea41cbac8f6d443bafa7c77d7efc070411f0ad04ec2d20b1c37e962346580360cee33b2e8bf98e9f32180c16bb79e360ee418f68e7f938b622e01bf63f2724fdcfcfcf4f9b4b4ca27b2de1df9f1f144c2998a6384d05c1c10289dad0fab911a96050156368a244845413198a523a4855cd50947252c5432dc14aea89955a948202c44a9522a678eb2dc840df8fa89f3e16a5e03cfd02239ce7e9249820f2a79b604e11a5252318dac481b13b3d77ae7dfce9699a3ffda7699dfbf1d385cef3c3e920ce1268fe3cfd2c2a41e7d18cda36b70727cbb08414a174d883f1f3731bd37c02adce2426a163fe3ccf73e8a5e40d8ada9f2a5507c79fe7791ae5f184b7e7799e33a0909a01cb5fa81fdd0767d0ac81e1848a19391a8871f088dd6e3f21463a65827ae3d6e8e31212201e83778787b61efb3c26e20b601f017b0742400299c718888138fd00c2032f5b1efb07a60f634fbb3cc6279aff3c4f5edef0e7d9e58c882ae5c50707e35b9f54171a7f6f116fa149317ebc30e3c48d89362b9433ae70f151c42a21853585661b2343898a1f5451707a3c8fe63b16479a51546a0b942a292e35d0cfe9792fc6185fa5f0d6afb55753de464992d2b265055d62422acb9a9b35fa065cea1f4048f1f87dea1f74aee753bf40e7aea73e429a9e4569ea39f514cca769ea0e483d298d067756a64b6f77c7bcedf0562a2985b7fe1a5f381509f3ab58d6ea6cd3967ba35c5d0b349c88a07183c30d1c1ef846908b948edf5fffb9523b4efcf554775e4cc385b7298aa57244fdcdc4f1450a73a65019a2e54c96db49b74999297f51b44590aa459bb7542e9a9ca84e284101433857b5d6fe62bc456f189fe78a3a542ca668096af0d7694254465dfe42c1598c8b51a856f87801e48c0fdf18ad30bd4348a452a64c151986543a9e87cb3589d54dc72ba3e95a9e6a440953153951a930114b2fd365b277ce1ca7345729c0cce81c358090475238a2c4c910090bda456378b4f6de7b8d50115e3142384337357e55280c7f82bcc5d616e9f1775804cad0080b04f85d343ca214e52812cc92f4ebb911e55c610a0b700702a6805703f09122840f210b356240585ac831630a0cc41970f8586bad8d236f6d0f2802f4d04aadb5d6cef00c20178fc45eafd7c28876c23975185de9c8aa533ace0c77bc2055a776cc79251559255d69984a92610a0f276f35bc9de251e6ab70aa470b415916b516c984ef8a0552092c16476ebc6aa090c384871c40b4a0d65a8bf179e278f34bda22642409aa81ef8694b716870b6f87f5c3098508a9095254b6a1e3afbfee940d3a7f69b55b03068c31a651e54a0d207ffd75a79050fca591586242850b135c804f62da46cdc53dada6ccf0e1c3e742132e8de4011e44ab23252554b9aa31bbf7de19bebf17e319c0b733ac7c38a7689800e5168d76867a05cb948b2139cd474e7a68a5404284852f34cc6ba304c6181b7d696a91c4414e8392c4415904b9189dc0534f23264630a47b558879ebd75abbe28793a91532e45c86229df01745511c8992c248448a2108137a5ba64cd832558404caa94294db210acac95598a91e54763c9ff13c9c4f0d302518b93aa1c296a9136d862a8a1703d0b23a93886a71008485f7bcf762dc7b9a2ad1624389201a4a40096142c570ca44140e2e6a2190460c518895376d8ada171bb19ab7a8b553bda3bfb928e7c71523415440d1e349cb9031f9b2e4e685265688e8801101820506151f3440eb8fbfe8c5f706f9f17618c4cd5bffb143214ade6219e2e3321c0267cb70898a0b7d7c7c7c7c43ebeecec747e893b34f9562def3c6b823c990d950c64555192c3de9f84b8192647e540590f285ce8d1372acb0a455b0d65a6bb3a4705969fefacfd498e15f4f698e47195926a06ebaa4470c6baa8819860080b53052a15418ab18a000804e962254d400c1123e498176e3cb971958a6beb02102834215305959c23001a13b809326366978c89151d4319e87fbb9f75e8c6fdd32870b98b75aa6b09abccbefad6f98ea12e7adec6d3de1ca94972c0d50241e5ba8fcbd9e5fe90f4dd7537110afcc506921f2d75f776acb097fa39686502c74f820d201731bc6bdf73a1df98b31c6b7b8e56dd6db2b516fb17a743085a50b98a92c5052a6ae6450998090354b3e865873921a85d7f8a332b4d242ca94152e528a413c60fc001e2adc5c31416403e7c5cb068b2a49c5a92a73781080adef5c8b1e29f94ba50c0230da421334415f150c45aa6a145c43ca1415151ea3b219a072bcf1d2a372e308c5e713a2157a9e5662ac3532af111918638cf5b74e59fd0841ab5454ce286121cbb0468a3e81676c42bad74e4d81f1d8c9454faca5266aaeb068117a7902801f616404f1913192c4456aa305f4c458c5df7bef940a167fef9414227fb5108b16882df0daaa0c30aec080c38a1537655ab8eebd4c5e0051a9989c99f224ac03b58486d1219e7b9bfc5da2354678854a930b45a714559caeae40c085a296365556e821431bfddc7b8da0f9abc445152a25603c2c79c1c58415a20c314a41a68e8adb2c2e12292355628e0c31c0913044242f002179923b8100aa2449a2087f5e80d1468ac798157ebde2a984bf17cab54c66a28a08a12a02870a0ac400b3e8a0c102c7aa4eeddc7b9350fda57a21eb6d162a224cb2dc40a96050c2a26232c2b23a13280030696acc88d20288928acac44a1008542a8b292f07cfa2d3282f0dd9f4781c25884768c94083468ca3227034c8f5de2275fee251cd51076a9a6059c32383e11a2b29c0e0d6ddea493251c546cc10a948d1f336f81958661ea7247e8c319303c8130e374f744c2768bca1a2a1e5c6479be0832b5ac6ea52e558e2e1a61d409a810e922e67844f296258488a62aa5f0c7faf6035561c36687c408c8c7c39c34b7dec912d6f53a4804595c28d8862f5623494f1d463478b3150b2bbe408e3159cc674c0a8c5d6fa586b2d6a31150aa39a093c920418042a9d7638633854e341abd7eb9930064d9ba317ea8479711bc59dfa0b542a41f4ab328c7af3aa52268a43292c0b00f166300521490c5d6260b561e2d22760b7b20802814a1845c1c110cac85fff09760ed726319450b29293d57bd225bc4c229020d0245add590425756d59b3978b5657a9845c8e7abbd15d5956575d2e24fd5465d5ba977074d755eb807a2e30ae13adabae5ee7fa47cf585657774a4948317e741911d39c251c3e4d310030982df0c8636c393429064db85061469836716f43a00f007d34f6e4efe101fc9e9e1ec7d99e5b4f8fcb2022890854921c0f3a12bbdc833f20b4f2d18832630b9d5d09f49e6672f73c77940005b56368809ae631644e70f12d818122c609ddeb89ba02958e3a8aa040e9b0d2015f22172ee00c619a53c29a3a172f49732f6ab5c11d83bd5e8fc5bd17bdf75e8c5e1b3cde4ad930f3d656281b6ea66e28718283c55beff021ca5bdf008408281c72de3e81fa4d41e5885185c52d1ecf3c9ef2a0cfc3e3b89187c79948e1f1d65acb53641d8742618c318a4631e16f142d7f83fed2a2c0f9eb429d2b80a32f2447304633943a56881aa463ca25446e50b23cbea6921cf7decb048a52171d26c83065868d933633c0aa13d53886189fc8d160055784cce83529ca99810e4e02859f58d980854e4046902162aae808d9cc29e61a8563e8419f2793194e3c76ba35ad6852305992a2c9c5093f394c625214a5a345001715e1a368c790ab2d4b4864e85932037aef9c14de030a93396ea030a1f304847598892223eb480b6796e214a971bb75a0c87902c209531c8c51198a9e3091a10a077cd1a117b6f7de6b514b46038a49bc78b28465c21c21c2de967947145bcb244e93bfc3e18f397155d2e43c6171d2d1477f838021119c58198205cad21316383d486498c0c1612518bc29ee4d539cd95255558292152c5c0e77003df7d230fa8b31c6e94551a3346ffdd616433278a8165ea440b958c2f201a7504536294099095267cd9ba4a62e5fbc84f9d2c38c1b59545186b40313c5a35edb88c7634f510e305071c3c51016b6864cb529a36e9c484f14b398f2d7efbda3cfea4ce0b8e3b97343bfe3a99cdff19fcea5bfb3b3b343e600361020550583b7f6ee78d1065fa4cc910cd04c56243ece138dd2017454076b494a9326747c6cc81cbc7a7bdece220b1555a31c7b3d33074dd3f4114cef40084808a2e34d3781b90167754decf57a29ec4cff6075249458a122c3d58b21327eeccc356fba07566f9aa6d3cc22427404af6cb161a3b4333d77eef5a6a771def49fced1de3c8b4e2e7fef5dcac1b183ee5dcf565777c3e00bd89ad4e8faf51fdf51d393ad476f6307ddfbf3c6cb55ffc2375e7a6bdef2b60e7d8c998224014316e24c19b65055891569a785f40800b6c4864a6c9e60d0e0d6e18fac6a35740149b502a33804520605fe685e2d368cb2a208092303500d0a854de2bda76916abcc114cd9914426c998233cb478747797a4c5cd2c8620cbe5729d2e978f605d2ed7d30b4aef3adfe572b91ce7f20f2e07d1b9a177b9075ddee51f742ebf8be672797679dae35dfed3b99e772d8d79cc04634c249e49c0d3120bbab70618c2f49783bf17831f90614ac4c0413282c5a3c6ae7d27ab731dc3b7ef6c75ae1675ae1ec5487d4ddf9e2275ce7efbce959ab351a2ec5c7dfb4ed58e55b186f8f9b645decef0db777a56b782291d2bb0d99243a5b46bdf29ea5c87f9f61d5fe72ab07335b8b4c344e4db7790a0716ace16b14550d44ce77cbc1d45b76a089f6f47d19fd5891802a1aef410f203eeda5160e71accb7a341ab2301e3cd0c2f2792e07409eeda51a6cef5976f47855657c99890f2e54c9d36549076ede8b073ed856855ec5c3b7a85cea8399b23078af4eda8111a03f5d5103ddf8ef6acceb6458b86c5acce552d1f6d3a07dbf2012b52735685550143f2ed3025d852e7986a089e6f7b04037efb0bcbeaea13253f56d8f2038510ac5dfb2bab73dde5db5f5bf5cc14b089cf4b535471d70e2bea5c631dc580f96c7c3b0ca973576aaed5a8795d7dfbabaa86105a5d6f6d0dbffdd5b33a98d58a1d3288e0b081c2ae9bcbb7bf8eac8e8492551d15aed47cf962c2aefde5eb5c6ff9f6d7cfea9ec90992184ea8704ab26b7f013bd75a824b2fa6ceb5bf909c716aaefb9cf3eda799b3cdb95543ec7cfb896575dd7efeac8e84101e4d4f525cc6906961d77e023bd75775d8b94ab42a76aefdbceadcf9b96e6afab1fd34f2d510e8770f87a6d0ea5e328c64c9a01a13e6c9aedd1c76aeb37cbb59c4b23a0ca4a80247061c3f5f985dbb99d5b9c6a2d5a673b0ad399d2b52736dc48889e4db4d257389a986807dbb89d43ad3d71c463329cbb5651e657dbb19a375e9aedd75a5e63a47e770b95c56c51a4268750d040e8b7c9dabc0ced5e0928ba973ed2e249deb895373ada255cc31d3b91eadad1ae2fceea3a3fcb3ba34eba98a88982c433abbee2bdf2ec0e2140356971259a6ecda3353e7baf8cd8218475ba4a469c1c6c5ae3d0f3bd7568856c5ceb5e7ac464dce469de3f1f69c7d3584f93d6e6dd52d482caa806b56a408b36b2f879deb2adf5e12ad2e04232a56a0fc882334b26b2f8b9d6b2adfeea3448e24ad365a7e599d6b2b2d286db6a0cc298bd4dc78e54a89e4db4ba572a964aa215c563762758ee9489930533c843cd9754f7905a0596af2e3c69a3745bb7672ab732de5dbcb9ed5914082412bcd9826532b30d9b597459deb2847314adff0db4b24f24acd8d4d4de4d5b79355a455e76a0d91bfc721390476ae0697482625df669c9a1b7df898f39d77edb8cd180cb66360372005a5a32a2eb0b0e6cbae9bf85d8956edf8aa73336a6e7c31bec048df8e8d3ab7e3edf808fb6a08f27bf4e1eb254a0c25c4600184ccae1bcab7df2209251f2a848103470618c35dfbcdea5c3fd16ad33953e9dbfcf65ba4e6541047a973a6b7df20ceea5cad473dddf3ed812e3fb6dbaaceb9bcdd12ef77087a032904b132d262899025bb76f24d0213c24c790346c6139b5d577d83e0474778824d16283176ed16d8b96e125cb24c9d6bb7483a97e3d4dc03ead41c339d83698940e286140b463ba4d49091b16b6f60e79aea3b0443a4a4b0d142131a1fbbf666ea5c4ffd881f6054b86111650e8e5d0f89564516dfe5b7f78c9ad34003a46f6fa3cebdbcbd8fdadb978bd03cc920b2300316245976dd5255ab4d6d628289ef2235075471a30321c9298d415b438cdfb63d033537561c92ef7e374931c377477d3b1a39567c256e787153b40b41e71a8a04127189471250858ddeae5d0222b48f5043d4e6a0853a3ea0881cd5d8b2eb271238e6c8d17a02d324c3965d3bad73cde4dbddea3ab872c6a742081a265676edf4ed1f3600d13911e6d6ec361b9acd349078414e5147951b65981c697a5ecae48786186b0410a585143e868879f362c7cbc2e7a5b1b1480a2121578c0c83c6d76a9e61b0f99abf9a6240f91a0d96c60d9b172d0ca9a82cf9a91d0909a130e36b7e6b4d28b8f95a5af3065fbcb2aacd6af1856a330f084f2059c1e38a0dac1d2f55f23c9aa75792866ab57e8124a2361b9a2d49721312123ac1cdd7fcd69a8e9c7ccd5f429568369bcd3898cd6638c408090909dd9bbb240c5f8bf2352d5f6b3ac185af4909d58866b3d9025a5c09a95a630289c58ee73f4bf23c5c29547d06e6673ee4676da8569b1169d0e04247ac369bcd66af59cd67330731f33a1b1a67424d2e7a5fabd5cc11f5b108f514a07e01d43b807a083a377e79d449b07a1425a2c40da87f00e181d1a3281005a228eae99747d1a127ac192f94852a981712226e41f335bfb55aed890b93af4dd16a5886ad5f0fa8a557a58aed679efed084b4c0f9996f986d61f233efd039ff309bcd66684d5765456ed06c31d9e88204455114459af3a8d04da83654ab8de8103ac30e23348a73a850a07de479b447bd5a1d087ac080c30b94ad1e515023a80b45511445510d42e8108af6d355160c88459f905b6f9f25b235b73e66696d6d35bd057aeb63d16a60128ec39138e7ad8f56e3096babacb5d63b603d0424a879eb26b01b705657851f40ec786b8bac85b2c6c45beb271c182fc4c10b0909c119be90ff08396ddd782121212121212122d14d95aff9add56a9eeaf89affd4deb4f99a0b752ebfd76a40a09cd7e05783069f539b177e6868a8e65fab6dad412103a7354d8ffa0fea34178fba10eac426864751b348eb859fcd66fe4ae3fc6ce6a4a6c8cf1c3577288a5aa1b4049d1244aeb0e0b4a3086cc4e1ab09114d22d12a6b6127ad158fa2a8908fd65a1236a0ae60c028d344468c1dcf9be979b8121d675142b56ce6e6d90c8d9a47fd3aa5717a340d0af2f4cd07f97c5050102da8ca5a2a2cbcb541251ea38a70fcac369b459970c60044b42406cd6a905543b4aa592873aed4ca599319560405d55cf8d9106c06865844d11a1414a49ff5fc6c36e380033086d4695ae1850e160c3480697e369ba1a8901921193a72b0ba5025d9f19cc8f370e6acd6940411895642b5da13243f3bc0cf6635ab81244c883e15e8cc91b3e3e5179e97bad029b59b599c413df16d20168140202020202020202038404041404135a0a05a505010105010105050101050501050d0871ca479eedcf9b4a838273c8d46731ccd699d439de642348fda02f3b6e648392db6ac7914a5e5202f4700868c144e70b3b505cb120a6a40910ace60c385d190149dbdf016e866064d2050c9fa10ce666cc23c8aa2160d3a41180df9e10211cb0f8b90e7e1685680822a10d0b8e359a04ca32d09c0cf4615252c7dc95251a6878f1335223eb942676a051382003941d1ac24e5e53f8b1a379e47a751153efde81508880d8d9f61f0b3d94c840936a86815a5aa92823e48ca38cdcf99cd0c9ac099f34ca0d20cc8ae491a40d49a2755b319d059a7d0803e6c6dc96432994c2693c96432994c2693c966b2196d36a3c96432194de6333f6533998c26a3c9663400c88068b319108d2693c968b2d98c2693c98064b419108d2693c964b3994c2693cd6632998c26a3cd642611ebc7582ce6381bf30f203cd0fa987fd039d8c762b158cc53a68fc56231af4c44d479d47f5027278fba101ac5e4c6a33814867009126ba396d0792b1426b16a7a21809809346166916821009da1e859a73c1a6234f26366e4c9ea88efad94a823648a51489c0a109b8121260929f6a45019d3407c6237804ab39b91151e341ae3517151220e94194fd2ec78eec2f370b32b25945634003a8b1d31a184cea28a18f9184a1b4263b3196e26b071238ac6f9181ae3e0888c2a00089e4c57412050298a898706333486a2288aa2288aa2b1a817c0bcd5711545640600e4888241ce0086c39fed38a5a15253e263b1183a8bf53039a2d25a7ad404cac8a0ee8c0d1b51c214be133f7eac0c08b391d65d2e3e948c2c0c5a580183261195c566327476cd7400a348245acd6e50868a2d488ae291628d0eaa27ad84ce64b16b668890d599c098cb501a07332fb1588c76bfccbc76791445514f4b3cea3f68138baa473d86da8cc69454415de6276a3383329b09449d670295d0173e168ba16e39b0d6da99ac69050e19ceb23a93c8cb55982d5a9dbed48925b1791445cda231ab9893310987523264fcf5d16a1c4ff858341e8dbef1d794820b8cd0811090b0f597e7afeffa36e0ec07101ea4a0e3af7fb075b7ee8d11a5e1afd36e2a48f9d96c36c33f9b11a55450f1b22cfb79990c289582f063b1580ce863319f0f8c021e45631429a0cf5cad378b8a64276231d9d5029414b9c950607a144579556881194f3f7a30fd3061a20599d4bd33994c0a851b4157863acd108bc95e9c79144571286ae38d2cf6a2070e5a9d4924e2e08fe33e80f0208a8ffff10f7e7e7e7e7e02a732a8b40bda4973162264230000201000b316000028100a0605837922877914333b140012659650625a481386c21ccc6118a68c418a184308010303224333db20008032b7768ca40293067ee7be08b5c69ab8e5b41656de253368f53d33c1b1157f2b8b552185f153abba4a5984213768f7ad618ecf95407e0e9e59b1056e0fcd10859fbf50b4b1326ffe9627a4b00f379e80adf918894bcc8caff58776dd18dd2bbc25e1b414ff0921983459af9c22e7172f3f89078ef640e3b59a4c9114e8b505f2cfd2d2db444130c1f5440de323f4b91a588548a43226cba31056f782447fd5048abd0ddc7c80484c590a15105532532dd03982ec74b5f1764a395b1e7dc742a80bd0180bab9e5f8c6e4193777790d0b0644b1c9abc298d12e70a859532e0ee9a810a0d8e1f7c6c68e23f8f810f2dd03eb4206af1e53c6a1d9037a288f2b8e2af821264b217c0d8879cff8e9f286e4d69bd61503aa6ad73f5a245eab3a626e3d881309b671bf4c3fc4bd1b325eba75100667423dd920277f5f55b4582f15e62de89e8f7c683025d4c60d1fc443e196d682376c47acb0a097c6e30b9c191b20b3b8b663c217281c5b7c6c51cf62670bab6afc38e4367bef2a39da17ca26d20843ac9b30c7ef5883f17550d5f86d68b0903e0722fb7b687362e3948e820eb83c0739b1fde198aae2ceb667ca837d08925efbec0ef33eaef7b314d5ad0b18a99234c3f28d7ac05c921129db4d06154dd8f8b5116bd7d7361921d5cabe981a8e97cef501b59a6e5810682c32244ce4259cf540a2a4e7751ec7638e25741328a36b384c51b43011c88fcd64bbf193acb11ac447e64f6e870d0c2523a05196b86b3d4859bcab361766c161a8e5299e78f99f8fa084709efb160f4d823a18bef9d4c9ff4c7016d21a4612429f83aa5909d9de4f17a5d7bb2a5db96b6d72ccd34f88900a1c50b5d9904501a1bd08f3918d028ee13b34c50c16d03b09a5984b77394397a6f506ae0508f08f54f76bf38f0960039cae81604fa012fc2fab8d1ddb5a532d062ddb4b88ef576b3430b9120c44e596c3fafa13e937fb731ddf543e0561da260f59d60be456badd044cdb2d6d6c83b8e41bfcb88a17fa067039a2ba532705a1c1b8d7ca2c5ef6f51c1001cc1d549a0a91986e08bd9d91b59a2f9707ab419a31fa69225ce92f4a969497d995ee4383a2c69fa4bd45dbb473acdf5c2d824e854a7f215a700c19ec1a2d1fb99d3b59edac1f6fb6fd806216589f70d26dcaa97b78837a1b4dab21bc3daa49ec1278b05754bc54232b4c937465ccf8017b38559829bdeac9321dfbb7bd9ec578488c46838ce17ebad31c54a9f31bc392a19610b20193e98aff6e8f22c001ba3d757c11caa702067e4cd6786b9693a3381bbb9c029c27ec63e8ad3a6b3f7366716276ec28c132744787ebe9eae322664ca3678565cea509a4a4643d68b606294359bf39fbe3c44141272568f0c446c032d958d1d598ad3863c88c1f244b428ab91fdf66d58a0cfb78c5adf580aa1a00cd27663c4cf351a154b950d7086b9ecdf83a277da2022e4c7e5df9c499d90ff100242ba4732fa3d10930432210aa03480fa6b7e28633707a5ee081ff11b2dea9018dc92d96f3f1e32c48f17588bddb93f10670b5b72e50250d630cc07f2a3d808c4d209a3f18ee63516a2122daa10491f7e55f0087c52c634758a2de09e2035ec2acde899aa385f1de0939e0000d5799438712d92118b14b877e525230f1e487c0798ce4b34514aadaac29549025dcb525730a62381174453abce145f9f269d10eb72f4d5cda80bb8f200c9bcd5507ca810e212f576ab96d7928a99511eac2e8ae3e18c0241f139bf616b447589995521e375340b1ecd5fb7e4a146e236cb12fd4bba8801023366b8addcb2c1287132c4f028179c0d00db0bada2c7232c6ca01ab99f7df36e57b64485ed7b153edf68209a5f47232370d5238628e740c6407bf6f08816f494af13a8ce961ecdb449a5bb55b84b005b93426c1f0e05cba90a5347fa248de011aa42efaa550b0c4425c8ee4c43d1b799461ac6b195c28c07052c8155e44067fbd3f764211fef2265d82297f6ec5e9885866b0376aec0dc7cf25f192c203df9d6253d233cbe842346617b682e6a3a058190a35667ea7fe67da678e531bbc690401e879a81c3e3598e3d48a787e3ba30f13b62c16415930a2eba2e2568605d5e6b2ebe839b13cc62237a966237abb5855dc1f423d66a915b0cd437637e8af47412b60d574e46241622adbbd647aef240345813cb055381ec868f2ce6b335d2862a08dea9413229e1b315a13c159e02d1084d6558e6863adf842e2ea36825ab64c617616f422fc56a73283ea6c9d21a88b86a488e65c3d534ee162ce47ccc1cf72646841b644de6935ad676b420478d3ca903190809a80e16b123eb0097a56fa2892f125d91c57be837d6b318cfc0a6ae6822df84a97fe23ba06bfb0720744b944c5804b4f846be898361010b445229e1998894eecbabefca0560ea062936e64ada2a55e299df83701de63a40c8ab5634d26ff9a4e47230c955db234276efca1033ec5d156ed61cd23230f848519632aa675e7cc9d384cd1cb0219869d7b0a859a9e55b747404c4a86cf062965e2ea913afb11633a4d68cdd2bc86ded0aab1ba2c76a0a4d7913efc5da103df876e9e4be39381f714d6d8a0bc10114bd21ecc8bba1daf91943f47f5d4c6b3f0b94bd26cde2368ad4d0625d28249f6e6e01aa4a330ac643e52f8d8217a7d1377481c4315abbb4986ca9fd4431216316a9c09712673b93a03a37c119c53f8676191fb372f33bd9f4208a241597526921237017618d957d9ed06f11fc0a6dbc08fd06a2e4ca6b886aaaec9980174cf48ac553ba9ba72c402fecbbf0c3cf42bbf1ead751cdab891520f4e8d3e23ef03940aae4358caa6c8f409e64ce861e1d95867f68eb8b9ed05393787c55f94a53a2f12fc9c10880d699479e824a51cd3ecbb8d31deb28658614a67fa104e8efc16395542e4af17d4ec2532c8419a7a26ee1aa5c809f8a4bc4dafa613afec55a78a489f356e2597a02b49129832633d23e41cb8fe481f8b34619753577ed5388fc8b8d078ebf04264632c782040315d2fb94934270a8b76a7ecf3facf5a366dd20aa3cdcfbf1cd474be262c6821dbaa1984ea66c22b76a4b17aa7d9d1c16a0f720d6c6a90a544292e383b59cd6452c0d7947e13873edd8cf2344cb0ef88f0d28b0d533c6a4127a620d870e13fb81ee76ba3735169675f4b3183a8eba01cbd5ffe3c4d23510faf6723d460416b0b5391b48cc0235fbbd7777ce5b6da91ed4d0de6149e5afd80e20fd53a0c51a7654947dbdb39e2da5152fe07ad15bf7a4109f2977b518a395f23481d82bf88d7a91c5ea30a094320041b89570ca8baa48519db63b1a88f2472d93b497b26171ba6e2dc10e0837b73120493d5ae8b908017867a192a883732d597d63caa529fc1a7e0964e4bb78e0631116d331b05a9e17af8b3d24c3e1a8999f4cdd9688b259205c7ad8cde142da13f1bf7b2ad38daf6e9b89a8ed3d7e8cc3bf38890514dd9746e31e0067ce9fc3dcf85fa4e054d43db972db3b7175fceaefc535cfa19fe5ed615b2e60b3c9676be640bc94bd7abd8bd455229b391ccf31a013f35d092d5831cc639c22936816a46648ccd165758305954015127eef48cf08c775bad227e697de7d6f798feba4a958b2c063ba14ed02f5e9dee3818c9fe4e107478352f7fed185acee1d76e1d428970060ab66a2975ca326142e45196256149dc1602b6ad6c5229f715cc65d58a9a591edcf0bd7fe9a77bf0e1ce769687469c86659812a1d13efb9b179f7b8fbd8905b21c5adfb4961ed081d7ba3c83e4dad4719b675b7b6124326b79309b37e8f0d8d0e6ce47fb8f64156e457ba85aa42102b08bfca87a5774db7a2df0156477368d4cc3a5baf95364592d018dfa86f38203623251ff1738bd6cd9b626bc26837da98416c6cd8d7e3a6db082e164c438f2f0eb945c0fccf4a05a4227f06c58109aaf8e2ce441bfa412a4e1da2396d7332416372eaf33a4609298a8718e4965876b1cbebfbd5b5bc53305e4cd2c9eaf20ec72363b2557c5e24e6c0ccb19807aff781f264fbb0a9ea8c525d0e116fd19b84a403e63fcc6a0d9c99bde5cadd107266036c9ef65a569f4e3cfa4899a885429c40cf1d513d9f80fd1e3f7c630b70a9b1f27a4b3e4813d5302c2becc4520632df599a1e9cd3999479c2420d46bd64eb53ed0ecc8d8c8c42876bb78038ade08bbfe0224fc52e423c335c1f3494fd4cc5becbc6ae24d6f1329be4b45c207ed3718358d03047a68eb772af6502c9cf002e890c8b473a5db3ebfda28f26f59faa2e64fec3f6b8a062c36d3f1e1e70863c9349986c208f05e1025212467b3c2bd9d57adbed0004c31b65a660263e76633916cf4667eb1209334b875106302731e244b5079b8358721ee128e2c88c50f721c064ebb8dc50f9805201806524329e4d149cab9c5cb29b8ad9d90724118944f07e7b105594e81217098a8389daf4e5f072f21f0e2f6e5858b43017cc03ea17696a34e94abb241fd58d787740f65de9748b8698dfd8b210226979060cfc6f5795f163f1b58e3a6a4929805fca4d8d2308138fc72e4a1c754877ddca18d291f28fdf7faf3c4a722b479af280ebb275b43a8f4d2038086f3a056ac76b0d1558d1db6f6cbe6fe7d1e779ec81cf544c99ab2aa760bd9a55813765d7f2dcd98ca9a57dc6309cd61059d7165287dcba32f49c2670ae1a90476b29d96e42e63d88b57860eb862bce1d2ce868c9b3f5eded1c09c57f86f06b4031ed93cb158b55b7f5e6297b4e3c6ea382ad269a09f8ba395ca042d978eec4c40697b133b97f3df13e085ebe3fabe00e584e1d4fe942dac4cdbc34413a689f3a302270a08bd171544173163c8ddc99b637f6279a7cf3e6763ca2403a9c614c9c5c582aeeddf87d6caacbb09fa826110ca6578f970514d36441dfaa6c025d6c4659f75afef2a19a31f2d2615c1fa5eeb32e4774f5d7fb0088604244cf63bf72fe8357cd5ee3d40c94477cc23600d128e452ac1629bc4353fc9e98d87e5305cb59596178c11bf45f64dc420441ee45b9a10c25a00eb5bf613d9d67131c33e743dbff319ea632e2c5e0199241cd82eeb98c6c85e2ebafc5807f3ee233119f988c7811eb4cba70d5c99ba1efc0ec65e8ba43f794bf215af33c539bb019110c6146248bde22cda3dd3f301d6a32ed7dc1641213e8e14f25a7d0ce45d6287910f3eb4731537ef812880f96c1518a8803a35dc3c8c584ab583391122847be6fd9726805ddbc1fbf9891f200aaadf2963c5a48c989a9be3cece59e19a62a609d4b22567f980c063abbc34421c0ac8ca13c9de0928fde6a7b696b6fc98dc705a5b109c6b0339ac9a37a0d1c19bc8156808187ae4cd920239c28c21b90ff50b42d458086cc9c84231e355c13c9ca04972c9adb9b9d260d5a8f2efcf82a08222deb2f27568eb6981b8217a6e9335a07a65dd5b070bfe8289067ac9d39f69c9a6a40c9047f77c4f604326799fb22baa4e6681a519cfc007fc087297e35241aa88d3d6baa7d5f005382a62cd1c507430e47394ce304018eec860a5b46a4ea909709f3bc1b62dc5fa1afbb761d880e2294394196ef58b1d33338eed8c2b98a0758620e7ed402410c5aeb855d15dda13653e4c03bc3ae9bde155289f3111337ede3c561a2cf4389703a7fbaf5fce5998bbe24d7111a556e404fcfd13a565daf59978f8921991d9c2b8cf2b38d0e88be10c9cff3fd6af71a00668a04d2cd44122f8b28da489779f830de54661c53da3f3a7954149e099a230e3f6d005a1c9b84c30ddf669486ceb036d64b8974660d5d6bf3dc8e1f4516a8d5cf1d58902c10fd06415a837dfd94bb478e161444aea35241b42f88fa551c0b30e3323406d4c2f3cfb6285d5618572a3bdae233ab8f0dcc7a4044a9ef7f251bc41e0b42650f4ac56450111058c2177ae465fccc75301042708f13911ef5d230e712adb299a410bc868b03853ddd91b47f640e6243460db545a2fc2bac89e19d442dfb6c69c03c21d2ec7ef3ebc2c1f1818b7a354c564d756bd8cc8bea3beadb32b29b146f09f89b8299ebd978fdc9d3c2308164517fa4174d4d07115b047aef3b8a7553c124982fce215ae22a62ce15643b0305f289f564029ea43fc42d05beb4b8148796273be4c638df0406fa48782cb6a9a62d62e2d875d10fb1a519fb14a88afe16f80ff4924d527686714470c6e5044bf48f87d9fd82645eea359637f9500dbfc0d9ebce2658d3bb8131f7ad74108c85e8cb5660edf847968dac34c307633efd1d38d4b200cd80b47e1902e06fbc85dd208b73cf4544aaa9a745cf116d071a6a7d35968183bcf988794e61968bee013ae75a913c0a4a3e4033b6506858622a16d837aed432c68a4cec268f76f0d2da9fc59cd5b640f683d1591c3cbf360fcd37877e2347234fb93b2efbe9379cffcccd624118e0fb10a1fa13839909786e5afacd74d270dd4288a04e6098ba699fc71d989c18322be1a290a0df44f192defc53c1deba24d66fc10ec9a5ce7786421652152663d69f08ba9b25cf0ea9bb18fe0325e2da6b4eb09379b299e2622e3ea858bd6c7b0c87c946684f35be0a5b90902660ee8673180a1ca9215e1c541c10a217d99ac9303cb9583f502eba130064c59121e802dc9a3ba14fead36f7aeb02ed5950b31f49e9fe966b1259cb88467ee3d824d7254110a883e82118e4b2b245a071f89870f42586589494b51803d7e8e57691b7e07fd441db30118421b7347efadf599153f7fa293bca18d7a933e14444251463515e8dbda47edb5450ca51e199e8bba4c71b6b9809329f4528f7a553d6ffe74e629938d5ec072ac4ba8671c7964975348eab88b2cf71ee0c26c1000d5af4fe0750d8409889cf4314230ada41ba759c8371c126691f22d55ff2a8abb51160d81f3e4fd8d2f805eb2d3a71b4fe41ded6914b6be83471865b6180aacf59eeb0d7f7897c9eae3a3b0efc7fff1d15804b4e0dd931934b238e5bb2d8f2d661a0e04d6582e6a78ababba14a85b45358f9b1e9fb00dfb29aeab251c79fb9cca4c9d53f93c764ec86335fff394d8dab0efb756e32edd9260c46cafdede7618a7601da1bf46b005321fc9c48147882f76fa36769d2f80e891ebf7de052f81f98c2c64751cead751acadca417cdfef73c7b63612a9e1defc7877c3fb7980e7f227dd4761fc053041af6ada0c26a75b143820a99ef8d2934d721dedcca5e74c269c64fdd3712862474dca98e39bbabe1f4a32189a78cf6c9cdbcff07b252ef0611b665986bc8ee62257c5cd1fb849c09080b63e02f2d5be1ccbe6c87e360b9e830e6da9252686341a8d477f9ffe947c678115ea28a650c190e12c9ab6558687fa667623d162d3308b80dfd123d50b193e53fd11d99ee817c1173deabed2c0d4cbd85d6fefc49e73b88d84d7a5d66ea55d51fee60442a03959c64695d26d2cc2e6379ff7c016f6b237d47e1886f60220a0cf8c6435d596c75b921bf15ecf2c85139a20e8cc71a8b1bc9e5d82cbf26813135b6ea409eb13662c76c4e88d1d15cb7beb844c60f76828f26e62c7512bccb6b2ff2a3ac9177f1415c27decc965f46760ea12b8c15021801a856e20569423f1238bccb4578a72ca75d3f627ea46408d317809ab7bbb9482061b1073fa778a88c94dbcbdbcb3e75edeca882445e7e240468ffc0a8781ece6cdd2da9d9d09d9097cbf060db3c2c50fc81cd13bf99c791de784a40f9c8ab2a473cbe2d70e466b974454360d68060bba97e5182642868a726596831f162ad2f0eb8267f76774322a78f797f17ab580b02f126900513e3f0dc14f7f61c02dcd2a0b25141d5c8f2a70ab73b5963c074d99472405b89246cdb62a6481cc9ea54f0172a9a4ebe518b592c9cb930c28294af589cc0a4c141a76bbdb46371cf47ca9cc399176a80bda2324e6166bf2bc7c44d69f1dee080f251d1177425c414db435a4631f5e52449e73ee6c4fea0e4f70e423538f4bf8caa5786eca43438d9637b7f94400a91dba23b19e7a628ab5d15baa4a36823fee3da21177caead8a629295e9bbe975b11f3cac825ef932d1d7504d4df9d1c0d4d4bc7720aefa12e41e4f667c53b40e15036d3cabc607c8793b6ee31c512f1709088ec9adb0410eabf02152f18891a0f4e7d6a0e9f2f752d0a3d69bf3cfed7e1735b5993ea6629d147e9f3adda149f671a3f79e30d422936860180c23cfa0cb88528409abb7a5fdbcb0ce5fc85c8f08d5832104717ce0e3011654ac1d8c23b6483d01a6d0cf3a90cf73bf8e88c9c060503c271e3d6cdd586f4b5a2df2e7ba521cd69cfd0fe2102c844bafafa489c1fb74cdc4b2eb77b713a5107cb1ef3d03ea7dc90c2f456b2b40877670bd09532e2913aa002cca5ac503240c14fb08c8528c9ba62c682a558a960ac6a93123d609780e329c49975fc0a3fa9b58481e53cd4805092a33b90054f1281baf175c7a6d3cfe742bff0a0e064eaa8d92abbea72b2a812ff708f3b4cf369d6e344a3d5274a88fbcb933ee2b871074a4952fc4915b97819df0a006673448b272f087534ff1753ea83518b1705dcedd52e560b71faecce685651839131ccedeb90764c159d0f01e6477ac42735ff001918a7ae6a8d889911b5350557febf7d1bd0481c4d4810a3e563a7f7d972c6aca9b8772334d222464d0d5c36e1ba6efb53145c26a7dd96cc2e36efefff514992272eaa92329bb3a4168b8cf294d562ac2254e9cbeea35b5a5bbb436422d5f32b0423c9b093f0300780a5ab226a203c380e36624c00740b6a8aee44028c9b402521ed5a11bcbda75c3419b9f8577090139a295153ea84be60e5ef7f4d32a21f3ac513090245f7c1ef7cd01625fa71f1d867c1ca41ac713951ede94c15d8b2f30761ced66c9b465b72053527c454b679180ea01ea1949faf8ced1b13ceab012655c05c5f8b6e656f58f560a86ecb3605c9c252c40c1507a6bfde2ae87633f0136f5fb50ad877c74de837d9b3eacfa8926d2417505ef18498f25b715f53a9c5420ff0dc0e684e8a32e882e49e28a3ab374d2a1a1059657bcb504f1db32b8543d5e07b57c5f45aeaa8e3079313c4985a1d0a73303c555b542c713a9167476611b7911a2d1100d1b3b6611002f6b5926699a817c173e00010ccad1e1732764cbfd6a20824f1ae4128418cc72761b48c57c9c8c7549428f5aa1dcf264a4afde107fcc814d14b25fcf3ef7b23409fa1b3f8714a0386d18406249e6a6d0ac6bc11c38252c6a9a26134e4f563ca9974a8634c91826b2c2d8c4a6030ca678065f134225a62432ad191c4c10bc76450f3e6af11387c2aff627405d6d733aa5879f9e309462a95722ef1f9534ed39e14c692ddb016a6db5212686efa4d357194cb16fc411f3d8fef15727c8753ee0c3b90b3c5c1da8811b5bc55de6b1f38d83ae801a3ba5d8a33034215deaf8c8ca969e41606b04ffd6049e4e5bcec87b407f7b17296e1a00d085ab7b9474bc8185dce544d6495a69c3ae4ca52c21aabd652369092ce0130c91b1f5ccc5c40b3b8c1c0c5783381cb83318e8a5fc8d014723f6313fd5218e31d857922d41c5dac1d90e3bce8c12205058fbb1f43268e3f80058e8e43a2fe660832668c8b7dd20ca71d2cd3341b03b8926b48a86662761d5b1924bbd123c1387307156f2b1b841bd712180886bb277c802f1baa2047a1d3e57d1ddb789c79fa611db4cea569a26a70568d23085724ea60b03ccafc35bd38e84d09f4084432bf4f2206edd7d1d58db6730fcc82d57e2d6a70374d4f96ce3d90cd3381808ea68e398c565471e0aea43fbfb3813e9c992acd371599d287099963052d3fe55746f247e4852495e88e91df3d46f108e2f1cdee07ca78fc98349e8697d34fd8d9828c4a5217da4c2f9367714cd6e36e9c5307378c842465389cc5b8272b926a5e198c8308acf0747e701da8ca04caad1ae1302b8f93cd535e0a338a71aa5c368e0d83e2626960366c2b6b64a8242bf5016658a030b6659247bd675a0c673f242d905ee9c4aa80052cba8345f8c77504d2f0e7e858140e142aff82018e852174f068ce9d4c2df9d14526d40f375907852edbfe2ecdf3f7c894a97755da362b8786c1c329bfab3dab98df07c19526fd6c67fa0149f9ca051c5006b079776caf8d435b66f2a1c1b815687d5431c9521115f7eea4222c026bc044461b371da704731b673f720c6e8db8c61a7fa96b2163d7f24b57e0a65e39f5043b01220f5d288f3bcf6599f4fb00d7525c7016b4d6880db322f4e00127c71d8ab242700392b2fe410b6fa66f242175e138a3ccac90420c2527b2c09ffa10d35485a491782a7efb6ebf912f89d4cdc1ad4711b248c44d91a3081c04cec41ea576f2820e512db31fa81251e26688a1c7c091884c1611e1374aa6fff8095b3342810abf4723172210139dae6f420d8cf7248fbad116bf7dba60c396f3ad76f859ddf78338543355b2aa5a4233cd90525b0c4925342c177e8101d99984c248090684ca8bc5a9a93cda14072f3307d04e7992dad97f5aae3861c01b43b4f3d48d10166a498213b7d0149d1a038f25982d270e851e51466a35e34f3ad41307d6824681c3f1e4ef5593f3d15a6330316b5f96fc76ee83101611c15e9f0a05d697d71c3237c5a56e46ff6f8e4ea7848a87853ca399948c137cfbb1a66c5969f1b83e701966c1006d1842b5c78847d31a14fb54cfe001c09e80a51c5c8b5354531aecc196e301de8fd7a97a202e1d2c361f359b5acd619d54e2afdcf4313edafc066a37adb9010e75e80d5ba40de489e978b94680b0ea8b01796a8f47e8cbb9c0caece231d25230f02b22a26e2f03f6ff8a5179a799c4314d1df19e57a1e06182c6fc2b1e49250ada9f6f597d7a812e08616f0c4dc2eba2250e39ad65db00746d755855e2bb47669f19d3dc774a1501f09173456fae2dcee8d4193ad19859a32d961eaca19ef827045b4a1b510838b16afd462bd58bca00962ef8f324f9d28be508104f42d6faf13d4a3c93d741318913bc4a5105ddeb4f9f5df51cf6067834182a95376074b2cf43c1e0fafa42229d35713d9f55509dae1e0534a56cb1f3d4f53451ffb07fdb29e534023622a242b0a5bead098ebb93f4e3244c46d7df491884426567fb975978214747c02e6bcce875861f27adc7a54c6c4defb059546719965a22627f3cb1ea4dd402eaa551832ea5d2cf358d3817165423c3bc7cd01f50ea09d433228dae5fb96550189330c2bf6a501c59785874cb4bfba79dc40ff497a07eb2fc8728944582031bbccee2f2cd27cdec74cf5c30e46a08a65449ca801a8b3a1a8ab81651513c5c0947df82f7fe5ea0932d4b5d20a560ec7d58b4f90376c9a85e3d97987ef97c44f4eb6d52b72014728e0dc53480da02c0ff7fe00a4b7b1d848f75aeeed76b79389be595f54742a7b71a14de3d4dd820af4261196dd32f30cdc65ac869c1e036b1200bc61a68afe6da4a30be41f299b9b88c3623f280dcbfeebe511c06d845e5017080bbd61202f995cf726bbab37223b58197927e9e4a7d4a105b785dd4ebad44c1d5cade14477f478f584c9da47b453191d2be6f8c33571786ad9a75dc1deb78ca3b9da041315db3abe66abb95f611420c7238a7326e3d9ff9ff57c457f30b95aa6c6dcac62d9dd14b3d4aea655faf39ea2f631b9ddcf1ca3bb427ae65b6c53696d71d09b38ac50895a15e63058c9b2ca596a2ae911d82f04107d3785e2d2232e49cc57db2b31a38d6ee72032d47b767452de319912e22f2290e1e8715424989e81aef87329e9d3208cd1a2af323feec1853da8202662faf0643a73019f59fd06ee5a9d207acba9fb830ab11f6d028a83234a6fd0d2573000d53973872044ff48cf23c9ec1a302027aa856e09707f02e82407c00b2b2421c320db25df88abc6ae9811c02d5bf8313f76ef15854e9108609509177c33439de45409480a433efb9101a6bf08213349a7766101d0801ca619d7f54ea3051afb2a55368ad0592909aae612981546e82870b09f4160579c214be236c25356670e2abe8caf5cd1862ee6534b976f6f79fc1b329ecddd9cd1d74d7c374d5da358a3af9346531d51aaac8d55e2d9fa1ddd2d52bce2a6d8aa76692106883908ea3d653b6537c76accb0555240bb33719c5cdded6dfba8235612f84c3fd588a24edeab0634f8ea856d3404c9ac40eb8ea1692dd8aee92bd23092057d91dd535dd09e29b16a1aaf04ca59e814985f898cb8ed623d25c785543269ae945c70e60b12a01903f255a793023fa0e3620cb9dac5a6e81778094757b5a6fbea883a6847cf267ce56d31c7b332e4be79ea64de400409f7de484f1ebcecf954126d9365ff829cf97f372b69bdcff4d5ebb356a9db87525c1aa22ce0009bedcb3fe2835b00402385fb5733383ede6efe94a8017d471d097840176a660671d2293f73a0baa09d07dca9a261c263bf6249c014c46624d014e8bfb9985715dc52ce613400005ab0b621eda5325c983aec148ba70fefb44954beffdd201b9fd758c1bf67517c9b09c5dba6fff780788ca17559a2d524d1c9bcdc2943f09aa7f937d7010ab10243461062df560ecb680c9ab86fe70a5e2b6d6de7d104a5741dfdae17c848697c1395fe352c710f412c892f08039e9a83ec71727a15a700f993f7ca3e0a160efc4667762ada6d8a053e37c1ec8a6ca223dcbbcc6c04b914ee9879b1e859969e51866e992a3d40b2129c346fb60c3b85ad1c7f5e12506fe29052c9d4edf29a9a184a629e039fc57234941b68534733d5a45fac8e9a92a30a6168cdbd3624c3fe59d76e081d195b62ef971ed48aa83553f8371278a1a64ad4a02f0f19aaf5ea4a82b8335e3a38d4a728269343305e2a8e77fd1bd89bf89b000e3f383869b6f0496c81c52ed12784f6af1922ca01f34e01adc306b96193247716fae08200b14462c5db602738920307abed0bef0a7144785cdf47a7cff875bb5f08ddeb56e233658584f12053cc3abf1f43c97f0d33a5b2c16ca39a4daa2c04ccad2f6b4789886b6fe6b61cdd43e9da1343c241c5eea5af71451de0e64bead1c678522a62f74e94d0210d17f43c60b727578b35e4205c1791589a0d8b3029b1ce6578079efab340cc9612c28dd273e50cf0c5d2539b6c52388a6cd742f9f90b94bfc5f5cd056a6aad767e72c62725c0a113133c0e30d03a44cba3fa25c91819a42386a0e8be226cb054570383450d881c0fa41fb97f480d518f31f28aa38969c52ac40ba9a2fd38544c2220456d6a0f04144ed906840a4b60b40bff746689f523106c0aee9fa4f01e1f8d0c01bc1a7e194fd9b3e0ae3f3198fa4b117a07425115c601bdd051f18e2f70429b66b97cf0f9d35ba7edd517fc1b5e5cafc86093838af68d0f7824607c38dff865da0bb79b24345303a8f5c70b02d986e3c982184206e4bd60f2f50a87637c3310bf959d9d51672063b69994ba5e939a3d9203e7638a42a36869767a47c0f03f6fdb73a706a90a66e9beb940498c79ecc8e72fc8128b00ab8051aa54791ce1d9a7846628b8e3b8ba639144c0c19822fae2fb4b8559ddade03aad1102128b282d1417645f54bba80dd3c041badeaf34b9e88c9d23e2a36b092ab7d51fb6fe35a0ea8df2b55f73478adf181cac0da9833c186d828166974840a914d94b319c4c96a71770a87bd76842ce13229e3248817b75455ba9701b7a50adf6c955c4c7476a8aa481e356dd0d901f675545f74177cb129e413cfb0baebee7d76d67312b56438ef63a407d7e04ad58623542e4946d9b0591a23316a81745e3d79b379b8d00620887e468737a633a2da2c95444f43aaf3ec2de8c7fdf3b8b7787caf5b4d4a300d2f8af20e073ea1c361acbbd95acabd833b3d4f8ec66a26b5e10de166c4a0d69bd24fb0958faec0b80d47b19a504c68dd8d717f1d6047afd82916c6c0c3033a4db152b4886de6cd34cb315855871573e9cc71006168ae6140839ce85c22ba004bf08b3d67dc5486b09f51875d6fc5eb24bcbc1105d29bb560a9831eef49ef578e4b886692b2c48d42c0392809377c503ecc23beed8f6f023329da3873007abac97528eba20b0d603da4b7b54f409b320fcd9992128fa12a6041630d6d816dbca5bb47d13f7619861a48af404fbf3166dba912ff583234a42a1ae2ca748afbe77e70645d80681c1939681e85ed2a77fdd50d038af660aef7ec1660f0435a74fb4b9ccb64946505b522c180c7d8a7987406996f5f34b0e85b91291fa00188c7e4f061b98f1c06762f8e4c23fe5a695053a1adaf4f492c1d69bac46900f07032fdee8a3da34894838c2166838df0552daf7229d86b9808666a17777847dac80dabc0f12f889faf6ea1198a97a80477edd942295845aadfc40e3c5825142318de9f8e0d1d286733ff12c3334ac23b1a005fd0a2ed83019e18887e59e6cc687983b70cb6f896725e3a4abc11ebecaf4aa56332de2ee72ad26d63619f710829c70621100924a4682b925f471604d73f586e5b0d0ce2f2ff4d3f2292aaa0303a85d30e52dd0b097fb30b8dfdcc9925edb822488235fc7cecae5572daef5dc10e65048b328e0540c6139cbdb0d0df49f2d5a64f7457a775c615a665042186126ef9e1ee11a71048797e27ea1f2eb7b356621907a913107ea39b6586a8f358648dbf2efdbccbc7c4216a61de1b795a5c0aa98a4626189ea5e58a8175ab92e0e2ec4a5d5bb6967008b45c544ea304b1b6d35287093e72ae7f462fad5a76e2366e47df74a43601e92902c290775aee3dc6e61920e27db71e5001a87f82932918e1a1261b090b95ac11d940ea72f7c386c8269e1222e3d137c1a553c304ef1a6b7f80e1da71bac0afb087b8e7d42a6eefe0bd6bd667634b1edb78323de38a44d100e2303bd4193551494bf761d9c4a0d8b335bcefdfed41a163bda1a3b101fe1aef18c9c4266cca980aace80414e37ab7cb3ab2969c7aed4f7824c1a89d53caba4dd4343b4cf17b2af22319411e8c88bb14288aff11ed7d539ea7ea1ec9cfd24e4c66f0fae9ce72ec6392d064bd58770a86e3cec117481b65666dde1f0bf7f1034500e9e38d5d403494c34eecb4605ad9e78b3fb9468aa65862ee626794f3a3acc745052dd1307cd31939f96282492e5ac976709c9dcadc590fe568c9cf03430c5a3f0ca120b77ab0ae5bbaf6ab943651afdbb57e140408ecb12a3c263bf311f36b81b864f2a79a2cf344625e1453a0c4c6adfe10289ad90b32b2a315b01b0deb795ed774c8f23056a57fcc67cdab6d12c4a66e4a4c8e9ab435c5d6e64055452c77ca17cddeb5ab306bad6ea85366bd1aa0c331b7489f8960f37853c67dc4751374e5d030b4e05015eb1ac057210b6368c2062c059d2d220440caa1d3fd18d56af1ffe250b22a410b46766dd31672c017b338551829236f36f1682e205428656f0db114d36220d8f3d654643bc869afa678b7e721e18e2f3d9eba956e18e04d789853701701c5c9bc8b5d1ed81af6b0fec24f963506c9ce542d8409ec924401661c8c83c6b3db149c1f969c17c1eacc38bf0a16a766223e1cc387b0fa78442273397a4ac01594de3658b05bf058573025c367b4c372cef3403c9dfdf1df196db27e8940e019524ff71446ac176b0442e3bd13abeda29287ae2219a59675d245ad19a713ed68e47582cea60e28a7bd64911f2bd191c20ac00ee42e4c00117af9e223e6bc1595da6d687c6325ad3d069982d9e409b853ee996ccccbf4fc6758f0aff94d25a7292a6c3eb5b03e3675c545ace8a291d032ab8118d61abf90dcb0e8c2f6ae106518cba8da391a3a6426e1655ba7220c2f7ea7c3173119420ce93bf0c242a8d403392410b1bf63b8e0019aef70629478c8a242a05e7a645392670eec28d494e747ec08f21bc4787493e491dc9963595e3e8be665658d0ad64a42ccb4aeb60a549ff530892eb7110a49aeee288be540edcf5435a13f399a00bac846666f1cd872d91d4deec9f89ec4f14f17b56ddabdb100cf6cb9d9bfdceaa47678229d6892e89ae3fea8a514584731112a3a130a2695f2cf341006942dea89fed3700fcc103273a7229fcfd058fe7aec308e9d33c5d9662aa7e7e25332891b063fcc0fd0d52bb24165d3872be75da467c760d2cd5e4304d102c026e4dc715ad706c44392919302f95a70aa53ea846971b3bc9cb3b81354b02798a7f04aadd608fd2645bf3d240a60640474ec645befff096a96a5145e18a7ae32c032eb410d9758f106c01accbb2faa90441ef7fe1f4c089cc3410202dff9b54a751e7ce96bba8f0e43ac61865fcccf06c79bfa48a96ee0a9684e7298f62b9cc1d21a88a37231bea3abc15fded26e69262cc710f3209a4af8335bac3b95bce1dc7a8fed17535c14d99cfb44e81235a0bb2240771e49485c882b5d66d0b52eadbe5076bf41344901875b2049497651adc6bd67dda7113aebf4934aed709c8e4b71d14f8232b80eb5e7a75b00d26f0f3b14401d99800f83a8599c046c0ace38517af0df9496d5389bae1bce05cbdaddaf133af950ebc7df0af5c69de7615f2f2420bb4125c681fc2dd88188829663a2273d79db9b41a6a4a99f5fa43ef4936417badaba617cd674fbaf4eabf215b91668e32fd9110ae8642a5fe54c093364974477c2b77d7708e46adf5b7d62139a0dfed1fd13a6bb67c4646c4a060f89bb082c5cf04716b4bd3c4d6eb26ea6a92f12be2262ded7fb12a9af5ee2cc291eae8155d24372fe0b5069bea8d7351502268700de7137d535612778e33a4ef619669e70e917250c52e48a286f436653f7b963bb5f9a101ea110f791f45ff8a2be458f8e60f4275f4c5975f4f8de20606078da07a2556f84ad8b4cff95bc5d7dac13c79e91f33411386681178980bcae9569b2da68ade93d88139c426a7c10ce86226b50d50b7fd1a7005d747be28d5b9a72bbde8398ca2c7acd0d27c44ec69fef13d1a3bb5a58ff6ebe120da3ba22f7c4113d8f413016ac61828cda14b48dc5bb3e87b0323a9c2608d51020c6cfadb39597df162ea2f690867a7a8df451b599433d3fe852f314a26941abea7e0cb66643172e4642650eed18dfaabe8009ba812dd28a35a4a463834a27e9f5011bb33b423951621839a961610d7d56073c589071d990dab879d6f6c2c6d9fb0f2b7cffd90ca1da0549d8e6df695888cc8a5c3f1704e17c78da71e4d367375a782b44002d37a2585c111a01e4db268140268ac3025bd1013d2f1193813a4e82947da387cb86282e3777763519449211acb4faf3700baf12ea67536af0ee36d1ce41c58c880ca34fac390ce902cf2eae18c99664257c601216b6f248d25b810f270f5f8e956c3143a0282f5113aa79e5003bb7fbcd363460b97a7d354e4e6c30966752fc2a3a3265516a347c29bde52fb9886ca0cf2988905e9b1ac715e5da5a7a8027da085c4b97f5b3b207e5cf0054b28c19dbbd4837b0f10704f49cd6fdba5e2f1ce4445b859b74844e34508d046ea2afa80a34473c314a2a0754f1dd28df593f9bafdd07236d92c82c4cee386a4dbdb4a59d1211b815d7181b495319f7abcb191968e42a49f4309d039a2a2762d482db2d59e394a3551aea0da6308559a875fee85dfb0419c263e5f84fb467443832f6483562961ad0cf58509834d2ac71cd86bf50c20f105d77090c6a2fcb62336deed41f48ac01c3b3b574ec0ffdd2e418d99cc9cd7021a8517dfb6911c3712e78ad295e8552d223a297d9ed14ee0dc69ab29a02259213dd5e28c316ba7bc2602e7a4ed5ed087c10750e0fedbaac507e22db4bb2e52b042c7f4caab85374c220e81baa06fc031e6e41e781e90ce616c2b61152af596623f8337d87205a84cc0b863bb8a6d7ed42e6a5711209a66cb54e588400efac29bf1deb90bd6f53081da06cee5bfceed882c1cf653f1465fb997f5efca3b9ef29de688ea83e3fba10f8069ae4362162474838ecbd81cb94d98b4c2ade78db235a5517a1dd9d93e1d8f316eb5f4cab8a8770fbe63f07e4f33692863065321255e77325c6a160a4a8853c9e800af2c823219790d48025eaca42a6a8de074ec760097e0a6f7254337d401cde69ad38bb71e93c9dd38a4684fd5456668600032394d8092847846b1c95c84c2ff70722a34c8b5507e3b82189e52d3776d6db3223030f74bf439da18e061590d18714da8b42d8efa5565f6fe1ff643f628584cbc9f416094bf4820320dfc3702376cd5187cc7120b605fc0401d020cb6cbd9b21394f9d5b212191544749fe86b414e092b2a521db5f64a9288ca27726838190556b56e052fffc16041ef1368a3a9251e6ae91061280efb5ab04448864676edb066c31701b855620d83e0351a019128a961b02ce0f5665d998621f3fbbfb77c746fc03bb1c10a5af155c0979d684d062c1783904b162578835cd7c9b11843ce9387a17447967d2f0d41f2f7eee91e74dc31e4b765174a42bcf244be74c1fec680d76fa9dcc0b403adb34422eec18394017362818b6325304f867a3a6394971df619fc7ef149196cad605b0ca8d305309748ca60f945ca20e2429924fb058588412943921389eb552251738650ba5acf94748aa0547c9788ef846ddc03660b207ef64959109f211f43bc6526a643d45d7718f5eeb71aab3c114f6dbb18e34f36df125a72eb59ae72fcf63a19b3c3326a67a64c39e50ab74585a9468ab4b63f06d2489436cc966418b5eac57c0936e428bc49a61d17118468c9647fac437f3c044095631cb9b9c0f2b7d2a9504fdcf145a935dfa08ea6d4628b51a19b81e3b1d220400e1ef467a1c03de54adb3dff462b743398934b72efe1a01251c2ef1f94c9779dec1a06d167ccb7e12630a8f1a34e89ca7bf85b2393490f0bc449fe231a68240498c18eb2d6be9582080311978d817d726b0d4e930c096b4baada814719062019f021f58ee4ad90c5486603315bbf13d871a552fa3a585f061b7751d207c367a1bdd5a30e161a5c1e119a54d21c6199f14d243463bfc37dbe3b51a9908235973a9eb85e634e1c78369e3802ffc53e7e333110b108ea305760c8b24b0f5530ce928681f8419aad272de3ae395d783fd8faecbd25cdb9b3708d38ef84036e7a2e950c0539ca8578133c916e0bdbdf473392013258ae34fb570a2ffc164c569019c6c24e41dc58d8122cf3d5701560966713f11d78f9a4ff4733193295a019281833119cf12c2da066e437d40fcd4e014e3774a8c16ddd029e2b65f8d03ebef7f5c51804bf0cffcd191e366976d835cc5c736a6f98cc41ad398cf24f201115d1a2fb94d065eed06dff3f84cce883d08f607aa4393bf2fb828b530541ad130b9b8d39aed74805d9cf9d05e71af013a6c38a4a178257a1da02a9a341b754f9e7e1a9c56297643a6d296e2e43b1dc2b2de68683bb56831080adf6f44d29bc6d17e888ec126e06262d8167498c766802ac736389382c190e2d7641df6a5315de872b44b04440344cb94b4938806a11d40e5b120cb515667758bfd7fe58e36de0448d3c8eaf4de2d7234b0abc05d0a648102032f5548e715fbbe5d3ba52000432c3a5026e0c8ff9d9e8750b6e7df393a6e9361c9506d1c1ab97d5dd3ca42049a7071862c01f9abe7ea0b7b6a174f6c819564ae13f3b02145f663cd57d6353a774ab8e24380f85321f91ef48c1048a3bde41816560e9a4d3cc2b9d77479dcc05155ecb8c0f5424388854cd3e2fd13094ab08dd77833b2e0f4b5253de18a99d94d5c0c55e1ee7fa28c243a88b9e1b4b255bd343ad98ba6e4d37cff615828e0fcaee25be5b408eeaf582c1a46832da1e5e1da3aaf1c418e830361043b99fd1e0e38fcbb9f813b353fa88d70a6aaa900c1b6280b43520041ecebf0deddcfbada32af35dd6c012eeba7f85821926dc308ca5016a0204414056f93fcdafd7580fffb3ea41d78e2946c3d4de48ec1b025185afb55350ecdcbf7b21d255ca433be1ea031f15e55a8344dc7d424d641c9fd8ce25c21020160321f7481aecbfd9acce206661c56ab1ed1a828fd321a593eea400eb686e4dbbdb7d5a0a511759505778a8c4a4a1ad7fa4963c0e23b43da3343dd1a84449e3f2d0146d4d896b817746042ec7536fe3716589c944c9d16358f56d4fca02a2f5ab6c1691b2543dfe35818f7f96051560ef97fbdc4651fe99c4765aa3d9044b4bc73707548dbefe737ae4b2a87a78fa1508a4460fe4dbc9531005200b9916008850656ecb29001ddc095a75049f328b674c162f0567779890970bb1d70976bbbc8c3a887d03fb75671173308c7190dee10babf937b7c4ecc2ec9f374dc4b8010e176c818fe29f9e411b3f0c416a1bd1d45c30b6f81f902766f1c1cc92ea1a28b2daa96dc5949c80f09562dea0aba8b11b9f2afb8575ccd457b0261c260a7ee5659ec9d5c99187655b212b20ad16e0955c807b503c124435558178d4911b80f505ad99c3ea588b99d9b06ce06e0b9ed4c4e42c75b2acd2e8b888b174fba367305431da6a08c0a9b27d1bb1fb9c80eecd7af484a13babfece322d4605a65d9c64167d620ff184b9dbc455884ec1a715ca214c22440319d81896690f7d9e5cb6ba77fc0fe99d60482058c8ef90284f326be6dadc82d92f1b490883b22996513c8e5f3b9b1a1050659063a2f5d531cd34eb8e469b1782cb59ffad722b4d680738a5637bc88df5856129c9df3c88049e3e5703385391df2d4578a11a80644f7dd1802c23ffcd79d6a960cb04c2317c09e331913a21fbdf05d79d1b4076b2a09608e55e4042510fb668ab8149c5af8b35e6d4a214a03fdcd6065fe177221b0e0d94e49c58d9f1a4b3e267ba40cef8309da161e55cb13aba5e842a954dae510d204f4bca4532e3ebf46b401fa67f1a0615b3a456239f398c4a122e24232a47db6dd76b00496a4825a44c2f4e2676b771c017092a7890ea123570ee5e787ba36843495ca94c0c3d91263210f5c6368e0a1febb8d4b5b25b01de8305b8c18ff243198d0099ce3756a69e426917dd0c96bc31aef061d9ff10648b6a8a5c34c3ac14c984648cc8f2f142f25c79480410d239bacc9a0c4445a8682455b0ed65d993619cbd4e6063516aa5bd8bea44dae2b6afc5c49f348265b0befeba6f1681b9a9233393a08a5743312033896e12a6b1898fd6de3afb4319184adff3cf24d817b39a5bb58771c96dc20e0bf15c3669ce0d624cdbc8d5be20908829eeb2637d81304f5dc66d8089f2afd894d272d19951b2bed680f7587035b8265709bd5cf3137c13a2a9df44016a0ec10c70f0a731f237bef9b02d5b42a0d484dcf9aca3e5da249cbf0fb146062c829031db4ee51f9bb7be69e7293f84f42b0247ceef420e08d7da820b1ff01afeb4485678b7fbe3f99fa4b056c481c2d02732732216a951560fa40cac68041d65217458f0ed169fc49c7bc483e13a8d1ddf1ba417d86b2cefb98fda9921bfafb1492f30751be0e37b09b83cef6dee46b13c659e5319c5a42d1159a5d99c1cf7981032e1ee2354c08dc8c2bf1e046c8cda158f704016b04098819c2728d011b11baa3e3614506f7c1a115baf5ce3aa06c10e7288b96ab38e050575703d835bcfa09b45cf6c52e6b06b632eec35494b3c85abada923f6aa3451d8b286406f2e70a5c129955a4a23ebd6aa1c94aeb83b88073185d1bb34540a6e0a5dee3fa11aa7aefe910f7e69eb739740611c1fb4eeacd022719c4d7a474bc1b898b1bc49aa1476ddbc0a5155ecc6c99f8e8873fcd5d55e2848b87a34d94aa627abb8c77b52588e1000d210e5f38105a8815ef155fa0b41c8102c9a06faa04dfa4c3784019680b25523c0d826f03d8acaa52541484b432f953a78ddb006d25b9603cbb12c68aee3335757111c556701dc7b8020b4f0946591dc23d86a2c682183f65a3b0bfc20883c90fdba9b48354dc84ac7396e6439f979270195144d75486a4363450c9db67a17ef0fafcdff692d17e7205eff188b72d192c0d0d2f3e3da970f7f689f3a851c34e5a30f15035712776348a4825d9ab8e0d6ae83be142d0537581cdd7123efbb0ccc075c7949fc623e7a98b73048e663c4a73fcd49acf1505140fb00e774025ac22bb9e45b7838441724ab16a2ef06c99388f3811ed1be9299834fb3f6c33e8a839bc80b2990113acb181aa0ae8efdae03e5bdfab90bc7abbe306e2b5568805157baf44b5736755d1902da11b9b8a2fbc3cb31e63f4eaeaab3b848cabcfb742a22e235d8ddf1e92ac2a193825b94baace9a5ee1d3ade1ccea161dfcaec5fc34b5ad2b7e41fe60e7e0653f1d159d6232d84ba15a3730c7203f84e6744ec16a22001697d88819e75d0d858211e234384aecea1074a160ef1f70fe05c2e43119802f116ff9c273d80d1e136c09c9b7e0ad9cc1fa3d0e07c9241426f673e701a7104421e71d71d20c2de36040af8b7bf31561815578ba6977db0f9074bd3ea9e7ee0eb97f135d088edb2db251cac7e800c7b9c519925bbccc159a9d82bbb56ff0ad0ab8ce6a474e54ff94af7c092b24f930f44a174acacd938c5c527f86e5f587fabab6ef9f6c2008f52845201a3002046ed1e64332f3de7e0607342bb162c9f0f0e060b40196c92452ad2850349dad186299914307a5889026af9b723174f9ea1e6dd6f00475d8739a06368204313a0f1e9c92945136128f0089769a2bd3e17c758c9e7b0cad7eacb0eea7740a4b737ca4caffbc946c1f55102f208f3e8e808a8154384ba91d13b9459effd8c5a44a227d56014860ee1f201fd762eca8390f7aa83c9f31896c893c4f68853dcd66ce6df6c912294b5788fd7785180b9b2c393c13d8ebc7c6364fa43cd739e2b9cec1284ac37fb73509c77ee72ea0b769e31a1307cce07278d4b7a71a972a2a706b5102c349868db1c4b9b71138c399cfabc855a56af07ea768b11e85f93aaf8700983e257313000370004d01599e41c50fe21f95c0514bba6a28a5fa3048d2fc3a2a9a0c8bb840ccc89ba461f9f6ee9c9e1adc9392cf8f9afd0834bceb66578d451696ca0d448d963f1c807b6396600ff1c64f0acc6a1452f8d56d8eaa354e536140e0db3e1e0bc10d28907fda202b818ba6b09eaff42e94eefcaa10c4a13782eaefbe7b43d8820fe3769c4e09dcad1f28c04d3ad0d3775ef677564bd69f8f9dccc681f649582c6f140b4cee454708fc457fd10658b65ffc4759779c6156f66818983e7cf15a58716d556ac23435c3b25274175e7f3e6b58017de39ba695cc44f7b9a6d01b21733d6b8c25c31d0c0e333a07d6aa413819b441eed77d26d3eb05cf81202b8f4fc2303047cd02d2851f39734d12fa727439ce45e768707535be3a07340b0fafcbab288bc2399b56d1067ce971edf8c6fd740a388d6cc4f8117a3675187468b462bd7012cea79d145a89e5945835e96eb2ba67322c212986bc47e0df040979d516a42bb5756c836f3524af68519d7ae6d95d20b0d9e716045dcf47a55f3ad8c9c6fa5139d0a0ed05017c06cfa0e8ebcc397849f61ee5340931d4462cb04698edd8e65b0c6e254e18fce9985973f01b55e543ad95f6ffd9af2300835b00c74864bda81f39549f60957a671811e0960bfa4b59551e23425e05843458eb521e187f75cd228b481c659da4b46db05efd23ddf4811828084345c4465cd175a3ca0c70ac17cb1601102562cdeb604cf4b08a925a8a486ddb01a5cd662e545f23a6dc35e5bd3f5d64b892674958332645457c7d6d8a98bb5c06a6363cb0618680663c3d2643f418707750128e72bb918144c56198d9e2387b33f30ca8d3ae26a529b8880b2edbc18ecec9dd5206405edd2acdf3364a014245287cd79552f2b2ff00882056aa471723fc2ad421c8249c9010dc166bbe38e449566e58a52937cae0dde5da3f9ec5f2fc72c5a5a2f51ec89d8724e5ac42dc573252e9783211eb5a01f1913fae78f9c1983bf57f0f5be9fc629fad8cf19ae13f32a77cce059aeb3358dd47a385e58a18f762d6992678a5d23d0058edb9ac3e692db0c588a9910213a53c004a01fb3e1ac81dc8182cb5d477a62c70ab9ae2d1708f8c4f1606893677b14ea5c6c6843b727706b96c25717805c7232c5bc890c92e0bbb4e1061eb9abaea9b4423141311a705ed820f775296581de46d7720b0ba4022d1ef80d59bb2c6d434b83105a3fc830198bc3ad56c96118616b95ef28ed8e4c4d64ae4170b46086fb3d8eaf909344f2a7495b890b5254f260ae77535ea1d2972c3bf3270c8fb7a1a918ee6c6cd05d48cb441d21fc37b41ad26be7ed527151cbd168b81db94f9b444ef4599776342c63e4a7ed32c50486683480c21b0e9d42926d7c9e5c41b153978448536e5a271ee506d48645f03abb43310867f838b996fa265a95e68535248aa1e3b0cd82f89e9f20b526e2d858a9d93f3b5fc4847c1da2e3e054561161d616307bac0b4210436c4fa317442fb9c6b6318c80eb00d72590db1fcc5c66f214c8a13e150378130daa411c3641a9c1e5e3632b568e5152ca92d9852610749b1343766d2b082950403f84315c56007f13f026b4ee573085f383149e060d8e2cb8183849955fff45f38fdb8f26d6f348fe31fe4d283de6ccab183790c82f6883d97c4175d9e024c3ed7d75a4e3cbcb2efaacfefb00c120ced45417b6018e839cae18aac135dbc213c664052c6a339810b010bfac9ec653b68ac5a60ea04a21b7d9f66abd4ec4946cbbab6f899fae2f2373289cf8e5586ab19549cfcad685aa14c7ea692c695149d163ab92b2918a2aceefe158253cb991d2ca2f8266959d9ecc2e8569e7924406503b5a4b643a36c9091317ba2c7a0dcda79110b907c2ea5daa252d2a52691f376376972d6f4ecc2933fe4a9b1542565c1e69eebd7585d3c6676140f3daedce76a1d9ac32993390fbbcd74120dfd31415078557314e59540904b6d265af6d178e8715021964032aa77db326ef0886a3d8e1acdca2249aa12f9c4f86026be3c2b91915c10ab75b7a6ffe0eff4d4fa602d101ac2292c2b31880bc3a2e00d3ee3cd5d72b164e34c2f9facad9c420b9aa300c22acaaaca6bc70545cd5ea43f0c986bf49bd10227dccbe4ac20db5ef7a426fe21a152d1811e8c264d454726a6e9e12b7ce82dc56e2c5e05a789f7cb723a96d48d82621226193257e409ea72cfd74e29804b9ab5a74f6e608e022aa7a6f31ca5829d207626030e805c4b9feacfe22c46810bfcb1559cd7978bb75b191ea29da81a7c412fa539a96d9dd21f7e1efe269bc74976076f16edf79ab6aeb6f8fd4d2f139b20d5bdcc10b5ec0e0e654cc1f21cbbe24b6e46ce0c96c34affd627c40e3e43078881de110b3fc0f78f89944a2e79349ee0cc9ab2e2019ced96375a05483e78fe97de01ba4d8e136ee042ed6981d01fe9c1c8b2802863ebe73533a3cbe0c13087eb0caad239a29314ad3f3a18aac3f93860456f17d61aae46d689da864cae1b84af3d49a662478afb0691f55c0c760ed1ac43c7be039cf4317187b346ac36b798793069eaf5a7fe67788c2743647a57edd475da4480055e19064b8e014d23dbe98230503595618143164df80ecf0cd86113eaa7414c404d5b82de05a8e4a5b7168c1e3f73c6ac2de0d2a4caafcb4d198f15bdc8d89091ddd1d07d4d27777363b19ef6b153ef5883899782788c78248c6b32bc0c785d8ae9da8cc1fb872edc2dc50cb748a16f513de3f10f46e3271043a4c9d57d5ea050d9683be3333087ad992763623a1697e122ef63a32e8e683843e788fe912e00673b1518ee538fc6c30f42977cf396d90e5c0b243f144fb07264c3bea68499ad8abf5c26b5a6d11915b4c2a26f5fd3c8773168d7d93cb8bfaba3d05a9cbf3cad4b5e43223876fbfacd0df5ce4ddda50a1036a5d61a6213547d2fc932bf449ae5d1d382a995319f77746acb561b5eec26531b50821356f2a80c3315beb2159cff848b7717f6fceb4925d4f8409fd4ec52c183bed7ea29ed6675e4a0faa6599e3e7df19a0cc54c2197c69f5b9409906ee2bbda99f36a034ac6d7d7463d5f5d82c84cdcaba8c74f21c764715b8ae828e67dc9ac252155df8e553160a4c0b159bb01796c0706bf6c8a5d250b214edafcd50ec36083a2779570290acae04853360cc4ff0371cae4982861c06458e00192ec7e72b5170a33d1a1394da07deb66fce1b0f361e80c624a35b149d110bbf7be63ca49f78d728782a284695fa492b15c8cc66f8fcc86c1c9cd20907ec1558ca1726fdddad9a80bc0d6838af405b772bfb60a413bdd14d48b694e00b4d6c94bafbc503143f44681a45c600c112224f47b8e4133cf779034f352bc2dc4e47a706d611fffdf2d91e911c954364302b5fd9966af0cd80ed7f9a5171488c75b96c48508500ff1772a1356de55639f7969d4a3e03d9ad3cf78dabdacf7a49833e5569c25e3fb04f558327fcdde7dc9060ffb4ffdcc39978768099aa5083f322482a0981af52d2262bf2f74ccda7fde8334ffcb68a9c6ecf8c0ba00eb6e1bddfe74b52d46c803ce1b33ca33151dc872b7f6084f01c9905321a552cf66d781009e536c803b21ddfcb3f108ab7303be4b00c8e82755a45ab275d17454645ce57517d77b0935ae143d223d6f2ab973d0c8940425c0132865b015d718fa072db1e6bb5e8ffe39d75871000027ae2c2b5f4571250810f19b5112334dd96fc20e727143d7fcda548bdafb8c60a286017ceb2ae4011a7340babc092cef5fa61f2f22c56d7593a02a5c1d9e2c9cdc29c40c9be3b8f479bdc8aced8fc12aa6717a856c867642e4132caf27b3dcc77671e72266e37614a6bc2340ba41d15ed6bd447417b79c011d711b4e5885a80361d3d8d4d05ccda99eb718a6d951357172f2cf4d1312b003b295de91ea20abdb4aa7d4e725e5fbc40a40768ab4b2c356022ed694cba3b6713bd799300544350f09cc6e877328366884d55df4242c492df37a946c2cebef2e04a2b828207744bcd2cd6fd8d6397c0722656e0970dbdc06697b543d9cf680ae75a5855bb5e5ed9aaa576bd5a8c6cda10de10aaac543df865b859d5c5440ba1c2110ccd88a0e828b4070f249c33152b117a4fa4afd4aef43e23a32044349adb96048a36c2af89a6f5dd68d4bbefa310d36bd8b75e704bf4abd5edeadec5ddfaef6db4e5b16b1c3928e10e89a25d31b5ddf929595b3aeb58f71bf9078e0b88643e5faec7257b14cfaa2aec566442b2ad58286a5d327768849ade1ad9d0deb3e1896ebc59415df7efabd51e6ae3f07d65460b88d9b65c322b68f601c51b01b80dfe5cb68199db620fb6e63ab3660c604b785fb68667b5073a6fc979d6fe18e096706ed8069cdd064304d806e750de92fb8c9d5372d69650c919dbc2228f6cfba990d5249741334838107e01bbce4ebf3fd2a6f850a6b811c50bfa3b07342b62f51aa4982c03d0834c5a4002647275110aae9ca5393521f3a36aae64681addd2ca4c33a130b090aa6b02988e6e5925938d10006c5c958b0c8d46595e39530634060652ed4a40e6d12dabc8a4110a9af667f1b0ca4598942e839e3d8272b899adab70538fefca86fe7140f0df97ff269acdded03928b4933df01021030b5c923243b5023f64898afdf609c12ccecb988a50862edd700b93ad52261274a7195b0386923d3f46a4ff4d464606bd5b908d54bca7fe06b832e169b516496b8c81769d8ed1fa101f556dbe6616a99dc8b99e1b60fe27a9979114b07db2bd5ac48a4e41659d7b62c10dcb8afc088538a591a212b271f0302fee5328c7a56f23de43a9d21dff87409128fb2cc0c0ea4303f6099b69ae5a5dfc96705e91e22dadd56ec58edb4ab8c8006ba6151f0194d84725758a075b5066cf0fe78e1da4a7c3f7580ccb10d5855e721b8351a12159234191acf7824deab59020077d78f4b257e374060fc9ae42cc4e097392a2d8d1d39895113d55a7df243d0ca6d18e307fecea8c15a0594f9e9233a4306406a73b965736b51669794fc2604c762089aac07fde77f44ae1c8db1701150146eaef835c350081eb8d2788011392736742d0e9cc329d78045a2f5ea57802a5af865d77e903fa04c23aa025e0bdbb32de99a8c0b09d0057aa7d3b3c02da9d5accc0cd63471fbe07c6d2585a29229ecaf2c213b336e9e104b105ebdfaa3870bd8099714e4f1e214f7976733da8979d5643da9eac585b21178f89e701ec9aa730c663248a385b04b8bb5ec42dbad9942186ad07a67025c80e0d7cc4a9cd59f12884bf9b164ffb7075022934d5df441ea3acd7f536591c06bd9de5e4ed8f2af6dff37a0e8b76656f945d0a964e848c2207ef83c35f169137a8256dd8d9171ea421cfbe2d111f613caa02942341473aba7dba47e3335dd55ee6c428e7cba7e8c0a52e0cca5f5dd775996091fd7290ada84bfb462606d7910eb3b558d2f166ccf7d04eb6854ae3441986e22919cbc12b5bb6abf54a2f83e1c9d265b18f1a60a3913d5a37d2c2c18fc3ef215342e95af2954f9e5c86a21b186d97efb1e1f7f193f833963bb7825927f764b235ce63162216dcd1268498dc1df43f2ab17a36dc84de6c732c00b1c68c7f5d30cb5fd81a69a01ef61e15e92d3712e7686b32846667e81ec57cb1642d5dc32558f7fa1e287bd86f1171af2118f8d74b33890249a5af44b488270d32e8b9c649766979b47d3b1461ea6a2cf139bd926615f58f0d13a91876d3595054049422d7ad03847472f962882d33c56fe85cf9570de6fc7989511ec423c604726da906af242025f2e9e8623bd5d95a895b35d41fa1c8b3969de09ade8676eaef0f897cd07320d5e1cdd82670d0baeaa7e99f2dbebf42dbaf5d044dc96d32d3ae6f42a7819c3747cab515609be4bfd46c5f7c425747964409b55b5a6ac8520a64a7a4748447d6866236079399978fbcac5974cf64d869ca3d673532c80a01fda842bbc205568d5d802b1d2828564712dc8230f5bd40e90625c93d3dfa6569d675af4944cba978bcee9aaa6c69d860daf2cacd15ce6dc5e614ffe6a9cfee079151cf464c465450454d0faf01ab6385dcfc575353cbea73a924e91f0e19a86f5a1dfb5eefed93463ec9ce2793862cf5ae6059b2522cb1c9b66cacf238b5ff6849587d2de080da85a58e7bd62b917b49622781763226f8e916de3395a62f7fcbebf6678f36e8ff9b42a1ad6d8d37e10a8c0310ef8fc2b3c59235f82cd94631344622d05d5c6b54f2432da74ebac70618495af2a5183cd6aa2e0f39dca0727021a6eaaab3ceb3d04fb61c0944a34fbd4d184356b6375b82a15f83162f6efe1ff1aca739199c8f07dc764cc36550341e1901d27f371d9a0c66e56617cdfb232eeadb83119350c00006a56afcb074056b33f2588d9a7cb04d1bdf1cbb039c6eaa29d4589f1cb4e3df3c70a1b6c734e07bb461c340bba5474ed8d2305d10a161b3363c648716bae30d5ad0aac591129d04dffd2e683d1525fa709137dc7d021950b03bc1b4daf74986fce0673dc89d48d29aac12307f76a0451dc74b722627a37c732f9a44c332bef57acb5036101d1f7189aa2b750304f94dec3eac852bf8acf30e0de87c8b1ab849d8fc6c1fba26d8e58f8eab5156eea8c95fabd12ed688beb4755798bd9e8b77e63298bbda5148300ac9e0d2bba71dcaf6a5048b330dfd3a4efbaf736d9f7c033c119ca50616a711c9a4220b877e5c020c35ec5d070840332b6a51efd3a930753443eb8077b37842e0da9c8e1075be8f8d916abc32bfad461d6b70510785df007d55e53ea4c86c00a2d1cb794701f6698be4f6a454b53c312394618a518e17be8a80d049fedc5a479d30219da391d137b29fa75209447d83d70f8500352c7f4242f5635518d36c1a35650ab4559dc3d2150bb21708699e14a7b923a791f128ad8c32a725d868b35b95b1e9a239008fbfa50f53ebc28870cd1c140da3f312c7041904d4cad9befe087579291336278e7c0b8fab09f30a817a2b5183407504f51826ef0d797c90177627f957aa720fa11b807c29ce9b435fd8af2cd86d25cedd93e8baf14f22a5be09b4e308de6f5258a07fb3552cb5758aa2e84ae1d6a3039e6dfa9b4846acf990fea3d8ce2da05d1ca07faaecd70319341289427931098b67e1fa42d31405214bdd3288566a0652a3ec26a2a1f3c010576ced1621d31b32648cce483d70eb526a7c8cebccad874ed5a69755c988cdcc8dde12ef7d4e728e1d4320154d727152b331d1c56e1e02cf08d52d8a7d5afda88ce3387502132b2c2ad433dae25d33d8df52f71d5fb99e670da51815221fbb636d13352fdbe30642499526eef065bb1e087fd0bc3c569f51d2ad885426386910acaecbb9facad418234dd731d53aace644b85cdb5bb242e7f4fc21e7b88f9c07448b021a66ae865930d0605207fa330761000af923cd0f145da60130e4e7383e83b0fb1b84942c4491faf19920c83100a5bce7133b9a35c030106bb89676e8723a9a679ab0712bbaa4bc5e774fd657d0a3080dd561e8fa2d86dd5b4ab9b7945b0621081b08a7081dffcdd08df0667837dc00b38f07f94db0e3ef1db3ef9629bd7945611911db7ef87b48dce661c7df4b665f07948e66652fa4782d7ff87b4adc66141d7f6f997d3d40281d4b6847cb15663ffc3d266ef389662fa847c7dfeb4ddd76c3c1f5a83afede136e313cfe9eb12775375c231d7f2f09fbb8b1d7d4f1f396d967802c59380ce518425cf2c3cf63e2369be8f879cdecab3111442c48454487243ffc3c37dce6a28ebf07ccbe9b2444119572e8e4f3f5c3df0be23697e8f87b42a98ebf57847dfb879f2776db4d46c61bebf8795ebc309ef26ee03179c88e9f07cc3e0f82524eb4845c248a3ffcbc206e33898e9f27ccbe0e806414ab7c30eb4af1c3cf1be2368fe8f879c4eccbc0121332331f692b88fcf0f38ab8cd4263144f2a46c7cfa37abbeddeda8a536b73bb1bee32fb763249ccbe9ea013654c2cba9eb844fcf07f11b75944c7ffc6ecbb5a694da9a822424e5cf9e17f29dc66a28eff8fd977b3aa4ebc9082e3c261e487ff91b8cd219261caa0a68effc7dee8b6dbcaea933afe1ffaa21fde0d0488c3be5c30c3f3bc878e5f0332997d2520215d294e41d171f6c3af41c96c0605db344cdd76ebd83a345075fc1a9e34446990ba1b06d0f16b48c2be35a9a1a9e3cfc0ccd0ccbecb940245e50ca8a8cded873f831b6ef350c7af21a841a8d6f16b28c2be9a1ffe0c62b7dd4b4b19c63afe0c5eb8bdf0f833243328ef060f3afe0cc7ecdbc59d01d9714c528c4d0b298756d80f7f86600661f6f5380963542d61826449961ffe0cc30cc4ec5bc0550734382c38c0a47ef83314719b4118a33248e1167f06aab7db6e101b445cc76f83dfc6c6ed6ee8a0e3b75966df160a991dbf0d31fbee9b0fd3da965097d8f187dfa688db2cd4f1db18b3cf04185f4ae294b2442cf9e1b791c26d0eeaf86d8ed97781047d984ab5248ee00fbf0d12b71944324c89db9b256245c76f33865b5dc76f63745b0d058a4d52c76f33845b99c76f23b419da00b34fbbb91db38f17d7416c6c48e88dc80f7f0db246b9ccbe1ea73717546248052172e387bf8689db0cd46c7313ebf86be2701bd36a312d5653f3845b0b8fbfa646ea6ec8e9f86b88d9a79735c565f6dd242684925a2411e911c5c46d0ebad500b3af07470cacb228ad2920587ef86b82b8cd40c2a29aa18f8ebf2609b7311d3f8dd86d755515cd58c74fe3451346a3bc1b703a7e9a63f6692412d9f1d300b3ef42191204d6846447528f1f7e9a206ef34fc74f23ccbe9e6191151fd2806a3099fdf0d30c719b3f14717b8d513452b8c54f43855bf6edb6dac9294eaded66997dda68c48fa12885db8bc4ed4d8629718b1fc31806a3dbea117a0486a48e1fc31086220cc3bba1d7f16300669f1e0e831dff8563f6f5e4b871e307edcdedebea87ff0212b7d943c77f4189dbcbc4ed6db6b9e116ff85b80b53b74ddfde2e5075fc179e2e4449dd0dbc8eff0231fbb4be50ecf8774c37dcde206eafb0e8c210b7f82f24edc46e9b92a564bbdd2e6ca7bc1bbee3df1db32f6532911dff0e987d22b0a2e30a112f1fc8ab1ffe5d10b7b943c7bf13661f053cd8f00a020794e4e1877f37c46de6d0f1ef88d977994665940c20281b3f7ef87745dc661f63d44e8aa9e3df51e1167dbb6dbab515d7f1cfa8cd34f1cfb8dd0d1a3afe9965f6a533cc8e7b907c78553172a3c205f7c319d8f1cf18b3ef4ae95136052b4ec8c7d70fff8c146e71968e7fe6987d3d339470e85aca025251e3877f06895b8c2519a6c42dfe99b119a3dba656a9d54c52c73f3334533433bc1b3274fc3271d8b716673c74fc32c7ec8b001b94152c49643f517ef86590b8c5573a7e19a5cc32fbae92ac35a48da920289e7ef86598b8956982f8e9f865da64a66e9b3aa54e32541dbfcc136e758f5fc628237537d874fc32c4ec4b8dc662c76f61997d37ec450e24a1aa2695e60fbf05266eb1958edf4233fb6ed246d095a4251b44b71f7e0b6eb8c5701dbf0c30fb7a9adc80b2ae822c2191f8e19709e216bf098b6440f874fc324916c46e9b8e48478c75fc16bc2c242de0b770ccbe14a716901dbf0560f615e0478a181e808c69407ef82d04718b85d9d76362061a0d6293132c86fcf05b18e21657e9f82d10b3ef3e59d2f2a123c88f1f237ef82d14718ba918a32c48b975fc16a870abbedd167d7b8bebf8756aba267e9ddbdd40d3f1eb96d9970281cc8e5f47cc3e9e1225a66c287d1dcdf8e1d715718ba774fc3a63f69d20d862ed88859224ae1f7e9d146e715bc7af3b665fcf8a24af2732ae204564fcf0eb90b8c55292614adce2d78de98c6e8b92912575fcba219d10bf6e783760e8f875c0ec4399cc60c71f73ccbebb74f204ea0c4533d8fce18f41e2164781018fae1a56d07c6e44f9e18f51e21643e9f86396d9d79302ec8687b1241114ac1ffe18266e71b3d9e6163cebf863e262a66e8b6e6df5f39f62a22e74fc31c4ec4393f86196d9d7e3c109d3d823484aa8c50f63b68e1fa6997d3d42185242451232d47cfcf0c3b8e116af75fc31c0ec9b61cbf201ab02e343891ffe98206ef1136151ccd048c71f930423765b74c60c98b18e1fc60b264c0973cc3e548a0706191ce2f616717b8d513052b8c50f4385db0a6fb7458d8ce2d4dadcee869965f6a14422b3e37f21669f0c9e2031ed20236212fbe17f29e216ab75fc2fc6ecbb694b156c5b367e24a1fcf0bf48e1163be9f85f8ed9d7b3f4e3c54f50531219613ffc2f48dce2b4649812b7f85fc65e8c6e8bfaa03e2f491dffcbd04bd1cbf06e90e9f85f80d98706831d3f7bccbe9e27a6f02b884390e6d70f3f8bc42d46ebf8d964f64da06a2d8691255f3446fcf0b34adc6266c7cf2eb38f46461288131c50674c3ffc2c13b7f8ac89d5e68615c74edd36a3a1b1541d3ffbc44649dd0d163a7eb6c92eb3efbe0555c0aef6db55f57442ab8915244a93c48d175120cc28b6088bb23404c70fad91aef58460aa92e284c50a144068f06b846dcba72b68c48da6196c2b8a9c13d75a6b8df562a96b1468ef231b92be7fb7758aa25a423abac372aa82a4976280f614b4a039fc3500cbc281654a872715bfdcfbac737ff4113066cfdf9dffe7e7ecb4ed945ff4a21c4d51fed26fd7158a2ed36fd7955a96ca5ddc9e283fcf5344d7d4b1f3eccecf41a78cfdfc1aecc33f0ffaf91fb07855af073d3fba51181d7d543f8aa6bff62e4753b587d6e09c73f7437bdfdbfd77144551608fe7049c9c10b0e86f97f3996be241b14b0b66e081830fb0775521ba200267a7411fede8474077b49782dc6b810dfaedaac2d447c01713fbf93adcea1da11184792999692151426644cf9b7eaf7ab0f5b5dfab1e666c8ad59eaba7d65e42605debe77f379c5dab3dde0b017bbbcb105a04450db2290e3764746dc5ecda6a4ad769cadbb13887d5a5a90ee79c417d08c61457bc32c4eca7635821b14ab263d9ece33f94d561e8b7cbeaaaebfaedb292d179d8dfa88d0ebc03cc4f47fbedc2e2a0f7cfde2edebc982ccd10b2fc6da8becd3af030e3a2c2c175f5439fae8e24ce9c7eafb0505c6181c06bb93301fc8302b60b871636232f20d18e61fbd929509a5e2867424328281f96417e290c2b6b59d85a98bc74b0097225eca6699aa65b3d4df7a39fdba8d67fea1d6205c738187046518acdde5a8d35aab5dfae35a74ea1dfae35a47546fa23dc01a4fa9eebcd9a277d15ddbd135a521a0f783a07a7977bf73eab539df3d5288ffe14d59fea5e0a52f45d7cb4d6bdf7e67bd39bd39d9bf3b997a627cff9bca3be8be6f447ee44eb40ee66df0b6e7488fb0981c661ed975f741e36275f0eb4a88829451f58bada52089dba7e56ec0c094dbf5d5d2abaeeb7eb4c4853eeb299c5df2f9b714f7a9e534e39ad6974ad7df8951613afd2a2a33b997eafb44274b6df2b1f57d2600ed5e9914701174b0703d0f5b359ac749da215faedc21a7665f1816213b93b01f6765511f6977ebba8147beeb658847e91f77340c02dea437f17153ad5b290725b3854cd53d3f5e56c0b2b195df7d2fd7cebfa3ed6f48dd3b78dd5b1efdfed1ecf093b5df7782f02ece55d57b23afabadda9d6512ba48ebe07a8cef926b02dfd5a5989e8b97eadac3cf4f30667cf99f791abbcca33176c220484ebc9efceac383cbb9aef37a75f0feee7826702b8f1535ed699a7c7c2ebdb2bf09c00420ecd1945d1cde3b9414733daec1acd185d4375ba1f6df69488aa9d1fa48f6ade75a900ba767e907ebe3de5a16813e7a4bf77d6e9aec2ee655e55559e1b74f5762dec18a38fd533787ea0b5aab54a8177768cd1d73cf414f6f3d847c0288f03333885b902bbe39e538873f408b9051be7ce34f71478391e8dfedb5f1ef37844405114451f3ffbb9dd32c35b2b1cb1ecb3b9e2fa3cab5b3fe3b8572e7876cc13a1e7829cb3ec9973c37f7e0ec8f94c8f8765657a6c8fe7d91e4f4ee7e146f6cca128fa59841f14eeadcd9e535b66d0eed58d589e35c98d4bdca2e9dac42d4dfa774dcbfab962e19cf37956de7accbcb5b83e45ad31ebf079eb73a0a79f2ba060f14e661d9d7e75d751dd79f329ef849c7ee3e272ea9b475d1e7073a3ebc1e458dc04acc1fbc1f9e708b0d8b29c89b01272f11be2f6fffc5c930b0fedf76e0872d1cf9bacd1e4fe9c0e9300ced93aff7571c07eadd39ceaac73d699eb7d1401e7ec5e7e9e13b40aee323f003e67c32b40cf3c0014a0dbfccc0c08cfd3d26742781eb6cfe8facc6e26a7cfecf41910fa8c02facccffccc73dc56f8999ff9999ff9991fe16e10c0cf7c2e87007fba10e079ce6ea3c1030f749aeacb820e83bcd3752f05ebd3fcca73f9dcfa298f07e7ec14d29afd3ccfa3f3f14fd3f439aaa27bcbf023cec14226711bc69563b8dd7f2fe87cbccbc3d9f14e9e9dae7beb6bf894b7a3b935efc2e33961a7d7bc86cfad2e0ed8edb2c6f941d5d4fc083846e7833f616ecfedf0ce0e7215780538c055fea00cf0d7c50106f811702ed7d32228e0a6af3ff35470955d7fae85d77ecaa3a1790574f4795a7cfc636a3a8aa37b9e1d103afa8fdb0a8fbe0722dc0d328fe2cce361d7d737e8ea6368c1d955ded977bc0a28627241df9fffbb8579189e7e1fef62980a28fedc79e59120026fc7027700fa2df074147840d057d9752f3dc0a3bc10be85e7ec2d38333c0def0f1042ef644370c17fbbdc40013fa80c1f0208bc03f02ece3100af003d11708ebe7d8777fb073cfd04e05d9c3300dec5391ef02ecea9e1e9ef80c7018fe31cfd3a3c36ebe8cfe17dd6d1af8127001e07ee00f45d06a0b7837396dde6f30878868773a1c7d3c2e3c15976dc3b590c1efa0d4f0539bdd74bc1bffef509d7749eb53803a5104b4d5f504820fdce5f89b8cd2e38707ee69d9023f53daead7c0d8182d62583438be5881d0b77242e59f608e260e1966b00598d132166c41511630bb05c4934153191c4e242c80653084ad2844340b44892e2cbb8a2eb6743e86a21e340661c4176c468a903059d35fadcc8a5d0f7b22115258b5ad80c76f74e9de552df73cee9ab91067b95babad3de54477b1790a16472250b96206b3f0dd3b5e63862b7e5433ec4c1c1c151de0d9749c78f73c438c88e1f07987db7d985242408494850dc0f3f4e10b75945c78f23cc3e113c7c9d0177ac9d28fbe1c719e236a7e8f87188d9d7c301ea0994144d760459fbe1c729e2362719a370a4708b1f870ab7eadb6db993535cc77fa376d3bc71bb1b6e9698d9f1df10b3ef8548dc222aafca983ffc3745dc66a48effc6987d1fc8318545e9939514e587ff460ab7f9a8e3bf3966df6533d1352625c95913e40fff0d12b7d92819a6c42dfe9b1ba3db721fee9314bbaa1d97969d4bf3e169e72ebb65b7f4d2983914888308a1d5a0da5cd0cb519e46dc5a4d5bd7ccea76c6ac73f71ee24e984ed83adffa394753d2f98a9fe3e4a41d3ffb5a9215d4f39e9c3b09e6adea75d5eb9f9fb3520871e44dc70d27309a8a7e1d38b1e2a3a5736e8576ec9cf3d771ce9d2cb3ce5579382e7c88732a4044aa124c4dca1f3fd2f9b3459dff6ea9f3add1a41ea7ea6ad8797e27c7aaad585ac8fdba5f3592f33011a86e67566452225f949f05b3ceed37fb582d2a2930abdb353136916a7264d9ecbb258e98514caa0dd5f77eddef1dc43ab76b3421d6d1daf72b4b669dcb4f56a7ebf7f8a6a2a7fd7a7d80d179d857557441d9f18283da911b56d948cf92d1d91011214e463f54ccc686b3e7efdee6492622dcc9ada79a22e59febb1bb3504ba1dc77befbd57f43d6201455f43381b1f9c94b29289d7900aae39518573efadeebd7754df5b6badb546c273d823a0ae1fe59add4d389fd322d480189388b0280910d74f1739aafa91f3388f93a39ed859ab4165a9abacec2813398251b67b9c631b1523289de777d4962560601d68aaf244a243102aa7df39e4c1a40440f5a1b53ed1435403c89410451a5269390c49df643911465091466274de2f96911653ae14224e404034c9c25444c8082292085b4c05495cc941bab0a09a486bedc5014c15f239caea5a4b43d878a500e2f593cbea02eb69bf595d6f3b6b8a9eadcab154bd513445ffeca12a4fd754d44092ea167cec09128d668ff4485a1ed2f891da46746a26661cc5008266124618eb4db289904145a4f3e04d28c695ae833721282e311df429888f981cb71c846104c40d16079df2f3c2ec45da4bf3e06485097db4dcc189c409170d5132b048fc61334cb9e20206089fd4469766a545955b0dbae6c6424893d3e89e4c696a72a66240d7a230b91971b910858de9470b9d41535b91022bcb30d1966c54650b28f38dc75995a41c4b16484d883f6ee8744d332524694c5a990a29295a5ea090a9e01014b26814252984c10fb90abae65812d1cd85021ae508520c9e7b22765405b65735224643905b551332447b5a351b180a38121cd5a14f7ea008718576bea81ad7892515f742a043d7b44cd4c082eeff1b82ade2a0651571e5b07befbf7b3fd7a93dee64975092f39fc3b28fc335e5a9a3fd561d39e93cbfc327f0764ec91da05e70cd371107461c2f72ae88cafae7f3eb53ffecf1f055d53c28fa3bf7728a5fe886e084aae094b8e6bc45eb02ed4931865212a2df06f286e4cdacea2d4ccdf55bf5a6d42bf45bf5965545eb1fad8da4105281c3aab5d6daa9ebad7f78644cb93db4f7ae31425b60495c16b0266c2a7c924b2c68d51249d7fd562d8ba0412194157961131ccb1358569155477750dd42bf5945c334c803605643d23ed0d821e426c9dd584b5475a5b58848a2ee08a05f2da22b5da65f2da2b38de4278ce10485b2684506b682c8018795b3d222144244d34b0a1f6c3e674c23809c447dfd489283729657091dc54bdc2a1a414070635045aa329c9116dc920a62879228754784114828c1021c401f045a6f5e701c28a0c85decbb4929595e39ace078327af5ceb3cb24407d245eb20fbf05ce7fe9e709d45ac4e3de46aa6ca0fd7ccbd8816d2de2b0f37eb588421c36360cd8bc456bad95ba4e9d60c014b3744d41c96904d3514bbf3e8a5254e4740ca5ac1d694b52cb5d3d2756106d59694e9510c195c4418f0b192c546429193a6bdb6aa7a2c0d9682b125142729ddb42fa76d9c3bd8770594ee068f1c1c491dfd6fa8ab1f5a583ed77eb479c1beab3c9389ffdbec62946f1ed9df7f49d27949c563211d4cca1d48523ae858f64d05652b8fec845bad6da48d72d7befbdb1f4bdebf5bbf535d467fadd02bb412337e5e40a4a1754940f593e1d59665033c25008c9587cb8e2507ad262090b38e48ad97cad6093161c1611ec682a5bb5f0f1d162690f51f51dd3af0f166be91085a44df3410d5e2042c64ef488a8c164c919f14b48adcac50b173b6292aed70a174f2ac284202d8f45a28f628d0a24b051990f175238abdbcdf4eb634594aeebd7870bdee5a283b4762aa212c4fc99a283f8d345841c2dd9ab181fa6ae771accd0043b3c18d3b05869112642d733b6c09aecf5c4938f351c5560a8786a927b14f96852b1d1103cd46cbcb135d9a0f1c60035105c28c24000bd82dc9627c498b2ee90a326aea36208582c3eec3ec7839d9a7eb98e823924ae5bf6de7bd937ca35e74537382a5301c4d545c3ecb779a87119b505a05f2ea31c1d43bf5c46c429b99b7d25506a5995991d719ab1a3264d0a02fa45a6e5f820cae68fe28aa8f3a07ff0b85175b4e3c28ead5d15d20e260c573fac1590cb10003d8cc81c73e824a130c4a3d8a57645a1479619a12bad103a1e6b18d8705c08b1b3da82e9c1812db270646173c4c283eba647138d158a0b475c86c963b0803800acc8384ed517dffdf063d2eb83915fb88ac15b7aecaad6ac6884aa6af01e8f1f9c1d4b66ac6858a88a2283dc5103a689d6b54b1514137d5719c5e538e81749f5d65ffa455231f5018c4d9ac088c29a9e20b1fd768f529149c914e294291eb7eb548ee07bbf500d595163c60e668cdfe6f5bd77cd0f0ecc2a54587cbe7e28d58e4b4dacbbf4cba5e6a533102824ad3015706d525e3a320011510ba2f5c1eced22d9fc6a10b8a92c8d45aa21228671c53553fc740e2f28af1d5a6badf5de7befed55ece94e4cbf575e3f373ea79e3c2deaa94b4ff7a769eea9fe9cd67ad57aebadb5de443dc539bb10e8d2f407879eb6f4344d2faaa6564fa268ce59ddae25f549953dfd5dba63776c9a5e2c3d457172ce9e978b9342bf575e463dd7ef959794cec3beba1ecdb858aab50549b490f23ba738b0d98090092c4341715988b0b29452edfad37bcf53ab7d04dc934f1aa021d8e87020ccdd10b856439c6e646c6e7deb94f33f9f6bce83fbf95ef20155c26b0041f2f584c469882ae3e86815d959477762faad22f3ea14faad22e381320db390d6806f50769ce51b185072650430cb4de9c7466edfab734ed7fcabae9f9fe67877fd117066d79c7f3def89a6bd3f4fd8f5dc6375ce5a1e8401aa97cc09812acbbd39e7405274beb5558d25329a730e4724e241b6ac98d0d201fcf1612db5907cece46a48fcaaf2a450e738e7dc27c9049f2636b93cb162495221a1c60583431e87242e6d60150a8d45792245f915a935115ac22b21506e25b9a631bbb751eb2d207121ce6d02d0a8f554080864595a4995a8c07635d59696d0865cfa4951854896231468c61fcf699d23db9248b636a2542339e7c0022dc10de882442ea10a71ca08eb76538859e7f220254e2ac812a8245964d3cca88429cb03f46bd5038c43d9716951754e0f5f5697969619ca9cd65a6bbdf7d65a6badf7de7acf007a3977349259e7f2ad6e2ea3dbde7b6f1368088b2cf7be408c327c691959cdc892fc80c64543f922f42b1149d770ceb90b26d6b94d6d820bb75d920e210d15c66293ba8c30c800269595b800354caa32dcb1904a21c2c40c533145135146c611ebc8421333c9089d518a8d28a60532c51598166ec2112f4e6e4b486c53b1499b880a308c1d8a283c01abce50085d5628a94ab418856021722f8c2ac688eb9352455c911a8328e426c43872014d31daca6292d6ed6008b18426c8608e30c1d83433614213904b098ec90428668a1626148fc42b26135a0009d0efd58da9e73753d0df453be8d72a471a9b4f263b2e3bd7f294ac51b9cbde43c2868cb568adaafb490da70322d6b945a3d44309392802b562a7c351bea40895c32687eb08552400022043425dd10900985b8c16390050728cf1c5c3d1ed980063b0e5dc8449c94021809e10a50c1e1a7846903290d8fc5228030e83069427512659b2c6a2990cc2cc39e74618176c8a18b1726a9447a31a0dcdd87106500d0622527c0693cd0526c619c70b3bb1e20c310c335fc419526a6474bb659386080b488c349832e8b89a34aa74315b4c1a435e609698c9d268a2f39234d61081813513d6701a400531660d2230148e0c6b30615c50fe43b8f5550d389a9612ca949973cea34cec725ec028a80ceb0f6454978dda558c62d670afa3871dc4ed48a7bf943164d2312c16051b86bd64244db30b58b7334b5ed9c052c339ca4b0863e65cdd38d25042722787822d76ab5c5555555555be4b6822e406e8f74a87d956b38a4d9dcb889102041b5091ca092bcc2c1340594535d5288ba86146f44454c491cf8e56c29c90d634c965af39569853f1de308a3ab7913490a9f871158504944f6ef2c4e109c4aaee38cf7a01a2f3937307bc48ae6b9693db8b0360e85a380c268cb6dde5ec6f1ec112a7764a729e0229c8a999752ea74289765c5ad65c540b6f692102c43a37281c128b0d2062dce117b73457cae6de7b7322ce39bf5a11a2463d51be5e29835ad5aad66a8ce69c2b9358e72a970d5032d7755d6164a000875a53c90356589cd99598504ecee3fc4ecea5784213391feabdb7d6e8135036c2ac1102eb7663c5ac73f971e8c858038e947d790919696a809127225f875a459eabbab13a842d814020d1b119e45e2c20b7ce9b41e68ed5b1ac6ea7033aad60059f3cd73bde864030df4cfc10df90429020347c2ba2086abef5182221e8480288a18f8f2c4ad69568ec4d28c5a88466445186342273fc9ab34805b546727e2c12860997430ed862aa85e02a6665bd091d8064fa0041c2015ccadd857eab7ebe9eab70ab9a1babb075baae2b076bc23af7092cc739e77c5dd755ab5b08040247386909f68b4585d5f9efcd832be79c2b3bdf5aabaa5ac5a14a5755555555f5eb897f45f12f2afe85c5bfbcf857185739e79c73ce39e79cef95828a753b2f2aac73b1bcc2c65412bccaf48eaaaaaaaaaa9c73aeaaaaaaaa2ae73ac8aeea1094d35a6b7d8cc23a970acb2b6cac8c84a39aa652cfb6de5a679d854020d0888c23fbc5da6aea1c9906214f187d381bea8ac12333015bd2b9ba5526080ce560821684c7d0485e5235858452a2f9b1e3d2a2e6a66cbdaa17e79ca83aa4987bc287b8a95b4532b5d7ade45a1f81d15a4c4dac8d85d13f5ae370c1a12591609b51fce94cd63596585cd74688bade7b6badb5d67aefadb5d65aebbdb7d61bc89aee50ae1caa5b1c95ca3a97ab3d5694872df9de1b47df7be322c9ac73f9de7befbd35de4d7d6fce39e72871cbd09c73ce8934b1ce2581881b6735304c55b7ba552c21c54d4211e3da12c49ff3222c30e4d671a22662eb2493f3175684b410e20f8a344833050854b703326c418284a451aa846e07a4d96582842046184b221280207174f43dd8a95ac2f4bc69c765afb92ddd826aad75cb5951e79fd39c73ceb956b56603eb5a3fd75aefb4d6576a635deb8b5bbdd535df5a6badb5e69cebad224131e74c929dffde9a8ceff3aa39d6f9ab3a49dd44201048820d2dbd57cb207b4595915bf16e8a548eb7358bb5b9f2aeda862e9cf3294b2e8273ceafa0c4edbd7786b2ea58c19d5cee0802d547ceb78450de26fc8075bb284cb120914ca80152aa80379eef648eb7f02b2f724b0e868b3d81fd66e14876ced50c82cbccc8881957dcbebcd864e7bf13d2f9ee7256b7ebb7ea4318fb2beac1c3d009ad6a2622e72b34935bd6b9dc438ee1debb2999752eef3a88cfd3165a45728259375655adbe6eb734b654b6a4b6d4d6b273bae86cf2d5b9958cced5555df7b1efcd4f156558e7aaf1365645dccec30f611d5e84757892089dffba8f7befbd3616b3959ab6d2d3568ada4a547b57100e1142391993c2443ba264296e85d0baaaeaaaae304b3f59a29899ed60b124c90a24ab1550472a512d40f69a6b897a5135efbcd76377ebf3b0ba9dd872cdadaa56d3b2727b9351916191799185a9ebe69c73a7ceb9bad5ad6a0ede3aff1d5f7b3969c9162d56447990735ec6a1ec672c972a01a6218e307135f9727142ca524652465456e26c06d5edac983c21f5cad9330d0b5fd57c39e7d76a8cd939df2851af3f14b06e974499756eca3b70ce99b475ae16e99545a286756e1b4712c77ac03a6b92a15f551e8ee6409c735074c5e8e8e48873ae644d815608819295a24993214763654d5d555f1d299803a8944a1cec4ae894b1191000000000c318000004302408a22c4aa2145bda011480104f92424e4e38918703c228240663190641208061000001100463180ca3509853650401c20a02017471a711a91a4bc6a7427e565cb979b2af13e082aba338430cb1c0cceb2217bae338af088b9d36a58908dc57e8e44e1c475e5ff138b15aa0e32fd60ab1bd1fe093f6c18529115f0eb08eabdf3da13ab0ddd8c400471f7192b2d1cb7d800d5ea4746f2b977e55047e22c88148120cbb6bd32d7122c245f4b2864e7248eb53a0017916174d22423ea70fa65d418730c0aea18abcdfbaa87536ff6a408ab9f87dbb6a1785899a9d784b615d551763c52cc1bbcc5b5c80e64820f74b023260f29a6161e293ecc4c00f5786af860962ae452630fe47f9f1900f49a0454a18701c6055c2a932fe60d1bfe709b7ae656ea1c522aaf060beeb9f59ae2be4931e460b1cef75b27cc9cfbb346787c26d8866591f3492eedbd5e9acb5582773bb313fa502b6802c8c59c0e25d1a3416a6bb82ac9f24e5e246cc72eb5622f79d7e0f68fa16a91421ea8cacdd49b997e31232e9c7b5a6222bdbbf6e518db04bb22d0888079a4021c1b9d7285996017be673ccd5e231f03997460aad3192e006973b9a154a7f438c01a58c4f85af831cfbf77a09203ae9077ecb494560cf27df05c9d83c50645eb9205ae911fdc78a08ded59d1dd13c8b60e40869bce968104ce6174afce95193f59c07a14d3e847ff04065cf03a5e2d014113549a81c6b3ec9a913cd9f80924a4e124e9d220ea111918d20f9a4911f7a6e00014535780fcb22927e385c542cc0f1be54aa478b78c1112308c496ed810011d93a455a6a0ffac4204306333581d4e3349161f41321052e5a38f2423249804e5e5014980dec36de065c8da69c46fcda1e4201b986ab90f75ae7d33819f68b3b8503360d2b18a30c8feb1a872066098bc1349b50cc321c8e6bb6ea07bd8b5b2753ef4b067e08819956ab20ed679d571003654a61cbd149839875707b32f02b3a8480bb56ab90f7f38ed33a9b73bfb2c5a92494c05211edc972ccd95710a30cdb38171b785e8d094c8ab9f26c112df5c9e9321ba718a2cdb72c5425b60330e4180b7f36d1a88ca0d64c44290ed9752c238a3c2a4234772111f3fedca578d61f544c9f4f368e74dca58c1ec07172ac5b6ae411f446011ec4f105451aeeeda754182093584754e322a362e117ad5cff42cae01deac4cfa23ac67218a14032af9898b7f0434a50ae4a9160e979bb5ee76cd69ba80e202506a0a414014716dfe8631a8beb9495337242fdd43aae154134072588ed1eb406837b8bbd2d3df8cf577bb1a09434296bc095026a90812524a513a75c524ad92b53d661504c4e93a33cb2b47277134e1e25d1c67b1c9cf881df4bbbc59659aa37939487145f758ac7c7a0be926231cba12b854e219ba6baa02b52718a958a310cc9e6cb110370a34ee0052f3c282792fdba9d2a7d1e38c46e06b8cadccdbab3e09c90c2ae0be69d81ae5150d51af6fa36ec26dac97daee8e195666679a2346d2e26acf3e09c4c63d6924f826261592c5615943f52bb29787eef8226926782496db2f446d666cb481325d55c4df02e4121699aac4c8e00a744ed6fa65897033c72a0991f433937991d6ec19d7f19a3d283af2afe5357b63cf14e1391f97dcca13e4929563ff0422f141425a5994d8e285dbb8b1965e7118212bd1244a21ca048b8515bccc6be44784fd7ad503824a4763dcc3b07b6b2ca094af79a0117adc832251d44f66dee6ae275a1f8b6b2a7dc5ddda64b50569048701eba5faeb0a3888668104a7e9d3a63649ea7235a502b3c8305dae7038ce93b0a7f322465abfda1afc1dbc7fb4bf34db34771dc7e4b3ba42f028fd1a7fd02bb349bb26567a880fcbfdc559933421d440508bd08537d83a298e993b71fd7212206eb3234cbad8fc0e90db9f9a44d8cc65646f8b8a1acf538bca67edea65e11555ebe9e16820f1f1cb7291a79540b4a3561f40d6bb8fc39e810a0e8235adef07ed0b58249f2b26fcd2befac81f78a91b2e892b71acee70590af61e9eb0d1d4ec4c9dbe01e2527ea56424cc391dadcbc0584a768a79f510a8f1e9dd2878a3593ec11d5d4daff3b369a0097acaa75d6034d1f183f7e82aeb1361b91f43efb539e184e2c49302e3828123dd3bb09a99270251b5e4d5e69d69356b283867ac013beab5eeb79a4abb304197d8dc2f2befa0f08bcc27abc4684c2887dd3a07bd00e98f220193efa397c70802fa05226b0251b0df18f220fda729c5c4300bd329dc183ad555b4abfbdd18e850ab67638ccc473d8f100b047b09c84148dda5ab711957840d4bfaa2263228a9b1bd59e11b9121b94bdb313717fa801e5612e3bdf8cee4dbd680932cca41cc729e114e04a21a5ac897e68190c742f19b6437fe635531c54086845ba18cab70cab02a59f25392ed277a31d84f28ec829fa358548eda9196abc58bae2b0620b7acdffc391721d6429a30cf6b1355a46f9d17bfcf352420087a469ceaa9d08e02486a825a4ce631ee3491894edc8fe54878966601094a03e5df8d2495e02c1842eabb310ef13f5957183be1fa8659590303959957e098db6a315f929731ca417425694cd31476b9519dec40d824629574007c82810629dea080d3d2879832683658b5171e94ad1b81b54128226d4e3748bc15ef61eeb8788fccfb63f062464096d4a674737ca5c11d9738aa0edfec9d3b515a73a40afde75d547611d21b82b0cd22977a6e5d2349d177a8b88263b6fbd3fc73018738eb0719b275b63ceb7c207951334dd2bf1a693806d7eae0c177d3a01897b141227eac27d1d3b8f9a64ac5a17f2fdb34d9f002f421505815e4b2bb98334db10684af4b02d19068184702616fd72251898a7c739a6d8d696758218253039be18f42ad7b74dfc94e1f4ade4eba9d7841e9f8be1c0f295a70c812e3a149557e99e6abae2eba3e706a1ed2a2ffa206778a5db38f4bf5b5eab889c1dba717ade009945a722c54c3537952b372aa9638ea94d72ce9a344e1c928aa5e3efc3c85990f1c7cdf4b2bd6c3f0b4fee4cb11a4d38062a9f674f0ad6240617e39a919b4cec272a071a643fd01e9a8d6557f92219e67f2d1445d37f11b33c4683a65692d6aeb095069a785c024226df9bcb415f3e4bea68ed2d0a1f3fa05eab236bb68dd38d78dc9d0fec4a7173ace244034cb184ccd18b720c194123e7949c97fa35a32df9d08981ea97140139824837ace7e56c5e8c69c94f69b48b2a1215314b56c4e9c87508e0c8de47633756342e9196e813894222f437319b04f75a3e4f6619108e16eea8328127fb68883c6c3930c93f0a5c457f5f76ae5fa89ec42613cf38d9fac85b9108813c30a2a8da18fc0ed0fe48782da50f6a00f4a77dc723b98578d7a41c0aef77b2f54e34c4c28e4916f1642f365dbcf3cc0245ed7ca2b3119f6ecb88fca4cfb9a2ab0da100145278620294f6f1d45ecf471c117bd58fb5d881208eb851da8197601f59757f03b365761e941f8266462e0c00161b32584173e32e175f6e3f262acb305b5f6e8d7168613c6067b02bf03671a540551abe92c63cba4ac434429651b3e95e347780b867964d7633c0b818bef8ec0db385d7920e7a834cff6f7a1ac638f4d3756436db5fde755db35bf0379dbec0d79fce127e1968bfcb5906158c530e530a4b68e4b2b0c7e55f0015afa6ae52de9c36a8c186c2b58c7d778d6aab87a98414152d47507ffa2a8116c288adfbcacc4022810e305f8fd73afcc58c76c67ad0ac449eef96e3d37b0014dbc9e3fe87db36aa495529cf78989d10e7d4fe0556e767496ef945592294b7e78de6b86c704fb9f62011ea79033adc9be421d16b046999ff214f2802be02b9e78aa68a7dfff26588085e478dff058b02e8eb864b40481486ee75c94ce260683d887cd283e2e6c4e1a537c2f30957b0b1814ff1cf78b0a85c4a52eb08f929da45cdae0bf7094b9280ca5ce009d7572ff5e70b2319aa12c604ac26c7de2da4b8ae56c68e5180f9f623a79822daaa7c70ffd8c52029e647c2eb78c14e302f8ca87702b5fb85c8a210c504f3dab08b62dce9853409553b08c1560d88610fc1d29ee6232c0fb605b0d3d0e6319dded9a5e1a11dcd6db1620183f306fcd0e9caf5cf58c4b490f90e5955f1bf3e0eb081bf459059d698dd88353b98fefea8f21edaa441b60d48e28d14fac2b2ad552e0a46674cf0f2ab9746846ad8cf7b38fdee17bf594871fda5c403aff8faf0c31b71cf38adcf66b79b67362d0f0f5e04887aea76b23914cc657639d67d2aa737b43e67c28a88d4543a80904ae448862f12a97f3172ace0e1965f820a241a2d154c7916c0ed2243f892f2dd60b6de03f6976502eb395c8f7435e6068ad9438702b1afcd8c217090d627df268c86f41c975d97e31253e7fd18a886f7efa1848bf44f40479de73a40740b5cd4ba9a723bde4aebe646c93de42249f68b6bad14ade96dda1f1515470d07c65c8163f7a0c7f441cc2c8192bd9936379d33e9815495a2d7a93dcbc12b5704344c4a70701abf275c6eac1d8f37b0dbfb04d4d920aafe0487c33022fde0de60614d6c70b78b086c315386108eb93cde66903083804b95d1da00fe5d80f3304d6152cc950f3529067b0429cbf261693cf16521dc2596530e273f7b6ede6a9fda3c76c429530e36cf85f43063a0022ea6dcc4fd5bbe22d57581df2c92a5e335872b7b2a79c1baf2ba451ff5d8de967acfb82cab66f345a5d94155a1f29d81d02834d5d75ee0feb88c6b2e1cd6ee95578c76414e367e306a188ac27bf704071ff2f291983fb3aa5c191375a7ecfaadeb1da76f4838991326482b8932e10450450a8359143a90ab94d2171c9086d66cb906789489b08037c1deceb37282fb2982cf18194669ab0024cff23878f42b6f3741b77598185f424d278be4925975576099b3d2369ce9a60a391a4b769785996a165f8686e7bb4221038799a19c35c7ef3841beea9d2759c6ff9e79b79e0c7dde2ab927a68c5fe6b127a243b3ddbd7603ce5f1247e3e711bf2dc0c5e3f3008164091dadbc71b3a89d0ae61659b7ef0ea8f528e8772a026a442646b30d9407a44d39b90dacdcd43f1d47fc28b478a960a08bba98d10b8cedb9ce9926cc40ae053015691e5969f76d24a67ac78aaf49d7653eddd69965f6fa9202c6673f62c48e1bdf92f91ed371cb61946d3063b90ad5ee7164934197ed18b0327c3e92c303e75273ab1fe563258e18b6a049490b00a012e64609cd55fb8f8d55d8a3b353325f6e1853b2994cd04946846ee9810cb757b595ba3bbda72cd77582ef5b5a85c849e9b64cf999851d8c53e8838362a0d15b8c99b0ed729277a28e88c90f6e7245e2313c3412fe778c9ffbaca8d034d0d294101629f36de688554aecb2fb050f1c80c68481bb656bd69004101c76cafaedf19005feae9329fd590d3d439f204e767a0546b9bd3e133950b63deb092b4235bcf19b3d412761486f827f316869bd98a69f1c8a80a27046c8a3cbe35c359a0facc5335b3b3c481c51f9f37af8be7598eaf0e166c7acd74628100a340e0628cd4bc7143102da0d7ceff3f56fc37bc0c8e6fe9a52b3248e7412c7a2c2da9394e8a8a040f613366800b15124b9a55e07a9183456d907a437b74c05060b23789467c642d12651edf462c24870b5c37ddc5e64f2d582817f6f5af8f0b6bacd49987a439bbf128359669c5da2fb639dae670b47e0bc58459e9a385052e90e635168ae980b392e52b62f77ad9a9686484c81524348466c3199b715bcfb7b677a1b79798023721e15f8bac8d5367ab479e6ebdfb620aab8fd9613e1ebdb39531b2f3ca812188983726cf7ad792d74b15e48952630c058af547e1236db01af426f200f599f971d43382f7d203825bafe8d56f1e5e8231b929d05017da1b269fd1f7b2e1bb94fa8f73fbe459450a370c0cb0d3f3f2c6ec235f1948be526bf4e1f5a9c33c871de0911c353fc29dcd02cc3d6240e46eacdb1c62dffe5ca2c25bd3866e16e89ee8fc99b2503264e1c5c4804804573eb2fb1cf98498f4e423665f6ab84f9748ed65ca28c72ab6d4074574c00e2ba7cfb5332afd19e381d9aed07f3b465fe3f5e8e6c26a2c5e0be917efc57336d6ed6d69b10de4e9d08e14aad82948eaa3fb977ff2aa9aff40c264ea316697905a1adf10e149077e6b1978b50994b47600509170e63073c425f45a811929d01d6e4290d6169564aa22f4b497f7f76c5704df3dcd8db3fe8507edf5c9007e1e4e23e49296a8eab7619e74bf0772a2f934cf3c6feeecf52bd6ffa6894824a4aee4ca7a2f6cc20769b3ab2c8620c1621beb84480672c3cd448a35601789f09d4a99ea6284f03fefd9e6c5d21301499c2f885d207691729a217ba8da1ff5ae85d483d041e7bce563e4bc4f5b09df73111b17f7141328483d1bf3bdee44ff7edd64777b08454cac5af8514db85521313bc92d9e65f6936020b0ecb7cf45706372ca1a03d5c5471b1024c6c599362806fbaa9ea19a2ef0d8a3f9a99d2df1b2e2a438d4e0d45b1b092dfad048a465d392b1c99eedf39c9d2d623b5f47da4df81f9beb7f1c9dd52695c7842301935aed54a2968ea2427b22c77a3479f9a3397a6e5b1b73892d92c2faeccbce35056de764a7880ecad1142913813580c3adf005f5f96f451808622d24dd22cca616b22ebeab422970e242ad6e4d8028a23029210ad08aa4cbed01025cbf4470431807f8d9e3693448184aa45bd437ffe5549aa2941bc12489c0b603e5ef395cb77136c113b150a88274515b57b8f44c2ad9d01390b6b179c02d8c492173afd7e0f499729b661dee50cd710f4b0a04a932c42d8a318f152a471687c8fb9be40dc44eb419909e1822d5308f94117853a3ab65c885af4f749732cab00a4a170d6b18654020e7e43c1b4713c5affb27013434c64e535b37463cfc5ebc33fe6378ce8f96490bcfc3e6550fc0d507ba6206411da1cc88b8f5041c4fbdecb9eac8090d56e6b40e58df03037ac0d3ceb0defe3a6d5291892e832b89339e08ba90cee5c09d7fca352fe488ae3d00ee52c29365a2ff89014cfa29b0bae5e472847732a5e250b40aa2bc86f5890346338249eb1876448337a0c6c08fab2a8c0f37778391be01a3a9a2022ac66ce0a5fa04283193c3bd2843130bd32a0d932b8f2e7e04aa2a8b044195bb8f27f787582a8b0a07c3d9ca7a7f17286a180a05962b813bfa7b68d0b56af2b956dfb08af921990b93b330b01f465a20d902d075e1be6ee58d18a1d50ec3c71814311e0db2306571365e4265c369e488143d8effd09c3ab8932420e2c3b4fccc021d377be0df28d3122d21a79b8f7fa331d9e841451445a5a26fdeec750bd93c720a131dff9fe67d6bf9c29476b2020b01ef3e6874fff27c787574c6b1603d5422c2dd053c33b3cfe07c1faa4fb8c4d726a365cf7914e89fb4157c911c7c6fbba0820ac95a71802c91e14172c18b57b7b76685304162909179b286aa0214f77befdd289d81b6984d2e201a8df162fa050915b7f60285b15c0b3b5a180ead4e30d8ae9f19423558a4fbbee1e4bef71eb894a8aa241ebae920570edc52c27c31a7e570770bbf6966643103cc1389097f050067ceb480e139fd751cd868b01859c9d0911312ac8df8c6b45b70042d8660e4e49c920ea0e806e127ea77ff56ade2d0c75307c02ff545adfec0b85be75cac2795585306ed604ba401bf6162120f73746a6177fc8ebd33635e7c5a3bab392f25edd3e63bd1ed4719121bf973fe3f07096a2e153520cf76e8770a82e19cf8ef4ebd5017f2fc6e86429833fd8d7049b75ed8a8194ac42764eaed70f08d550652a489280c81b21d709451173e588b92bb6f558296cec3a2ce2f30f493c41cbbc46dad3db570bce73a3f1de12d9d2aad1b5ce2c1af24779b392f7277b003a289cb8f6f240704d62faedfcae641b43211f5861f99d7c019d24da43c0fbb62859964c072da2dae2c0f192aa6cb06be1051ad22f214034381b119b1110c0dd66c51e81f2d696b13b49cd1a553491fcac22165574447a172c73a0932174c34b4f1b6fed96d2b551d499c258de4dac3244e6901bd01fea90f24816ecc7074d3240c1833f0c2bbb016bc1f08d37b481c026e54780f19085fde263be4f8a71314ae02ff0532e62e004010ebc9dad74a10101cad86cf30f04bbe48fb5b7ccfab33650431031f53b18255acf598d227dccec2a8fd8c9072999ade6cc54a0dc44c94b9e539bad53a119a39c533a4d1868787bf2f2e16ad4f5db6fbdbc0ca58774b6ea3358685d11efcc79116f2f13daa521557e1dfb45d07b8b05a3d206b8105ea24bf30a57e0dc98b9a03a252158104d8bc4890e2b930eb3958663a3832ffd1fba643a87b46560a7e205aa7720d7edccef230f09c0a32bd8f1054576060d894c5c93946e286198d705ad649de812c564d227e3748df8926f9d844f45521930e65ce71b78e6555283edce67722f89b322fc74a1b4ac84c5f0d1c2a63291d54b411be00696e220fee74982897adcb4c6ff15bb06ca0c512cd0b501ab15d3147a8434b9dc81b13b241ba9cb0cc1bf7fc4ecfdc00fa21f4d9f358a5ebe8305786af7eea25aa290d89daab5dc4eb1248ffa6230f545b15b724c2c60714c8b6988c8c202161b3c76018591cbf412adfd168c4f402fc5dbf16acfc466b279443dab5acdee880bd87c66c0c84b50694d037ab1f721aad7855d0568ac4b7ee5d8a7844ba5c8a78c3ba5e275ca81f5fcea3afd98000d06e1e7dcfcaa13c9a1eb3652b778459725440d11a69d452262e5e75ccdaeef458d2cc45c014a5c0328fe1e82350cab86cfc1475334cf1b68788bd64e23fdc9bb5aec46b8b483929cdcdd97fd0d131341c73cb7d1298b780d3b9da7cdc09cb197ff99e8b1c15947092e38289bd76052d63ce508013326f5e336d271dc13ea3652195ed7c0dd4aedc460bf8ef2a51d95c6f99ae249fdeb313f9a5d96c3309d322736324ee6cb8413e0ec31a9e7844b3beeed50f9eece435090717f5c59bf8ebb742851c308e80f528ed73b60513f810ab1b7ee27485a66b3be76938a65959628d009b1a5a6263d19accf54741965bdbf9a6ae761a526b2f2f67c28c0f912eaf59c87f3afd89d9a56b7912f593e08548d16b2850589f65579280df9f5cd656d9024653063738c92c5db3a60bd852633fc88d97b3e9dccaca6d7de30aafa37d4850b10384bbfff5fec73566046baceb493b1849ec73c1cc2e549d46ce60d02e600199c6660ce969d5fc03075a564ff008eb5fa9b451f7f008a157be54d508fd7bce4efc90976674cb0ea031df9485d601fa0188b1090a96bea8a83b419c982e411ea3342de3190c8301762b04bc6c16126f555efefe7dff8130a51a74d1cd6d31ca21161f0b1142f7a71726ab7898907b910e8042637c9a269ae4c448794dcb1fc882380c4fb0d47d8a4855f97bb53fde368acb74a3e5ef4b6d07f6b22c70a71777b9656d0c42db3fe9030df4081cb47f81dd33e0be4d71597bd8ebd41769639d6786cc7548fd041f3a46c2e13c845fb6557dc2d2755f6a66e366add5950d0589fad8424397f62a239780e111d0596ba216c8e08d4d7a02114df1809235455dcc077ddd8270be92f488fb430e3fdd914ec627e098cca3f331a6ba5009350fc2df7794ef4ed0f03125f67acfaff92a7d8214f555407274d3359c2d05ed9b5761181e33a5b801afcfd5df950e4f8d3ec4344d5e68887428bfc98ba96bb73a62229ba3f321666a8dabdd8bb7f51f785422be6b5f3a10ed484df861ca8e937ffa4471a6de2ac54073d809dc2523520a9323779c5417b3c1b891f8bc36eae23eabbcff8c0cfb74c954e42cf94a9253e537e72e0c6e94554c04d8f7e53532f9c1d2f2ac59ea11585cce8d3ffffef4ab1f03cf2c14b5340b49183d581851afbe7d5826f0984f7d38a5ab37c7cfa1ca35bbc44b067978f10ba5288808a70570100a6e7c578f7a8a388833ecf8f247db5560415d34be9ec9bde7c4430e4f87e6492314a2d0fd8b42cac26cd0fa39ae662aa28e8761ef9bd3f51f4f284e3cf915566dd05afc6483ec2e9ee210b0002ae09cc7f371348357c7c9b8dc55267ed3090e25949c33162b7fbd9b4f34a17e587b870b8372fbe9cb44b3b37ef6aad5d4e136dc9cf305ea3bfa9a2e7de54a8047076ac55d19e23208d7c6dd9abf2eef9b38520c507e4589721581e7a69e5a8834789b67d2a241dc5c79096928af1321df1c33efe29d54ee3f5502d4e1d991f4aa252eb82071bd555fe686fe34f6a9c9833332415237e0b8b5642ecb19ad2d9e3e519dc5a53588c5fba4693e4b72ddc5bf99000d2eec65120c6d194b7c2462beb378c91d0e2f40d48ab50c47597b898b3d55cfcd9bce9a7eb2be9ff8e431a6658b50188628be94332e8548d1361e29e036edc4035cc2f821df6cab40ee864066603eb14d1fef5e2ee000f9962e895d7808a2ec04ad107791095ea2f72a96bb49fae99495bbd8221d9cf77de33b12d97ee872aa5a276bb76419563ce21ce4306049b2df7d423e5568e47b32086418d31b9a4ed895616026cc0648926dc2f38ee64fd6bba7df25b1eae1bd4f6a20e07a3cda0b2522eea9a13585a8dfb1d37e00f03c249cf6b5576192ba374264361d18264611b539b9d5a58070c1e480929e35fdd49815c49c4cb5a5d3fb50dc68b5f8a4da0694798234c7a9b49cef9dfaf7ac2886e3b93dfab747f6d4142fc257814c9e808990cc231f0adaf00cbcec64311a8d2893cb2e92f78417f3ad2b94056f0f6affd1359a8cd3a28cffe50f6ac7c8c6fbd05a25d422943d4ae12f3a575211f3a6cd50652bc2d6a4df0f33e313f3b31ee2a63e21a2b0c76784003ca6ad9a8c6dd56392b6e33b8a5f4c580a371c09260bf71ad7efbd20ae28cc6d725eb2ced6cc95acd7d5d355d976c067969caf9e8c8dd4c6b7eef51121be8cef05ac359c20eed612fb3591e006c0e05256c355280abe216569439755061b687c035982c9f0a2b3d1eb61486764a0deb8c44a78662767128c70ef7818456c804b34f9b523d59ef1bd4cbb398ba4b532564990ca950662c88bf8fd53c163b455f28082c5a0fa932a399424f455c751b007a88740befb021c63719b67d2a2dd4719d026cfbcedb72ee54ed531007598d8650ffbacaa4c711cd9ec1e70a8118dd978aee888306eb9c2003484870951f824b75c082c46782da035d87f717cb946f14110fcf9a8aecc272bad93553cc33086ca2cddc43cf61af146bfcc40f5eae0fe8f9545c3fa2e7edfa4a3055c4f61831abf8202a56bbc3406ae3d31577e043c9ba6734d5617b945a512e03d8a2f385d0dea5aed1a670a08e53b810d5c748f72a149dc9c1be19148a8c5548cb87dfeb98c20e23db6bd1ee89aa553303dfb6b1ff28535094c169d6b7324408449e08ab5894cf210c854cd12b1105d96404c653d194819248a968c4430e84f666281ff1f24cf7907c5d66239353f8248f87eefa5361af39b966db4b4ada0569ab0fb6cdefab790737a977d64507f609ceb50fbb6b051da256778b9406fa81fab3aadd9f463a710ab71b9de9a42c1093057ac84f0b27f4aee1e8f33c7b48fad91a8ac2e9c37385902a2dd0893f48f888cadb7aa2fb385f7504f6516c07f897050aabe80113e06599034dbf350cbf3f31e722667ed7eb119695cc3ad06c8d37a5ee58a20853370ae3034599ecb3c7e16187acdac8dae7ef02be4fbb1cf913d9a94119d64a263b607341d758567ca34ee176c59c3e5620fb99db40b246c5e136af30e8e1c33c22b18bd92abadc7dc3181a0f012b67d6ef030ce552476fe3d169124dfd511aff0bf4a1b38915e44c88d19dc3cd2ba9b9bc39f485ac202d26fa457bae06062faecf6e0383c10fde704bf1fdeafb9cc47354afc3c48a01a2276cb05de1409aa50edd2a235b0c40aeed93a6d6d57f5ab9615c9c9d5aca1a616a9e06691517995366193f8712e08cedc4628940ddc97debb3d34f391c4a820db01fe33efde0fe8a5591ff115069a6036e5c49b7a8dff639121c86106f02483efacf48574e3041c55df34bc67a14fb87c7d9ca130e99f72d30e34cb7ea88bfe6eb86232d091a2944ad38a09323a730dc232a38cc20f4cbc130fa94fdd413ddce1a7e0689a0cfe585120166d7a8cb9be08c0daec008fcc17916374034697d02c39599f8d5082aac320877e141f5fe56983e6e404f1b808872d25eff80ab9978824b61863b803df0a785ea05c6c950cc1e4265e1f9f16463837e5e4a8f60b9db865c8e3c87e666c8f188e555f3a6a6229b2267d34f4b684011707a7a2d30ca57ac735abf2b3c596233b252d51486f38f0533f721aefb16f9c3d499ed316689799ad05d024ef4ee73d9555c90f0e595345a11d022ba77abc3fad251ab256893bb1861a3219f4641a66435cc835676707e020bdbcda1e1cbf59ac7a5e263c3f15bab60829a41fd92932b3010aed6a86bbcc010fc36505714812fdde29c1a3d2aefdbdeb4859c0cee1d3c78a1dbde2b1b959d211df795262274a6147cf5d75ab03545a3c71442f72e17cbad216ed89a65ac49fe4d4f806b809b46b30511cda7d7173dbab8bfcc556d88b1bb50694bd550ae28cfb424237a15b93c4a5eb3d63e05a6f1462c17dbe2cf60e40eb0b95cd437e38578d8e4fb3a786dbe579abad07791e03f04e38a9132e6d6584457edb641c47f812f6bf18e746c5d3370b00eb3d373532b94a5c2b24c6bcb217e16becbe35d42282a14486a4ae4145040d98611c968b1b01c2b9da488ca1121567e655f2bdd65f58c0805318b3a5c5c9ba07b230537bc2c2d8b32964b38dae86d3603d14a3511a03ed467a1a98226d305755d3538a203c4d5ca6dde2dd7d8e72f1cb9511afdb53a9c34d859263bce66970412d07b372c82bb67408e12a336b70e245a533f51566aff4589398a9562733596bb38c472ab68fd5b4d2946ab11b99dac19be88a69eb8b0243f2e31b8d0c29aab6106686377da0dcb5509ad48b730a3420355f01317d210091d8fe58093f404a1032f2acdb33cb6d2c69827446c7d33868911d416991052dd7226a2413b13da8e802c79554cee7b147bafc75e74ab522df53f3029046c970bbadcbf4223977035fc1817996512c4894bfba4e61e8a83139d2b48e6a3834dd4c6c9fa148f31d832785365ab4161d536528454d500515d46f3537c2ae8c2763d890762c012f6432966684feb4da5122effab38174f1d8ed0c13a3f2d75c08960a7fa404108ebffa5300f3f10fe57f23aeb4d1b4aef9915852831be8ab764185916d140555f332d4e5b56e5a8ab20762bf16c596aafca724ab2461750d0bbd26e9345614d411b5b00ba63e8f49868c47d7432e2b366519e9d5defe8b094c21b287936923ed85919df15cded67ad30c0f190a2fdb76c565d78c7dae84426805b964de4afd1cd7c693874337ecc2db83d85ddc1ff058a273a5cdc681da7ef3d2e3ed0276e82404bef70bd0d92df28085080c4397f0c1b3c81cc2cecf8334907da0247374c6cd9ce68de2b22d4edb9832580059abe873d35637a4f872533d55e46597da089bd8db257f2de2b3d580bddf7a4795c407dad48fa0750ca11661ee4a51e671a71eb56b2af29e10fc8916ab7af930974abc0c96e2ab866047a824e1631f200861eb51875705d04b75c750f2657c29c0daeab7fce65111c00d44dd457c03059e4a24a13f5e82f7d9e62bdd7f3cf85b079645a4f4858c93de507d364d9c20b24f425db0f56ac9197e360d3d099ff874fe48f2f536724607e268a45a9281dd13d2717dd8e67d1dacf2cdb1ef19cbd27c4b889b27afc00542beb39af39928c13f44482d38ff5653546af0d01304241263e9331b01acc0fbbee208db259d12bd99ccfd8e64e339de4499ff69b24f4779f0c9d51fb9ed7858491201567d9e442835aeb89d2716f92a005d495c51c1da151d1d558a3dda86893208d39389d9c72cc0cf3e3b505837b33a78ee52f324d869fe92106cbe16c51de8eab020d2b1b15154c1c109f5040c9fd7f5728542ba89c4f5c631db1043df3847869adb06e17dbdbba6987c184a84106a78d3199af8f090ab1e2aa0bcbff8706b229537766d5222480138dfd55c101308384b4dd98e59e5bf63c5ef10f70ca8ff3b07615e876ac3dd51e85469e554b9050478376d59e28ba58ce03b240e7cb204b334a9511c916d4c19e14f842e254678e253995f968e4f4234b50ad3bfd749839b5a3e1c32b6eb88a543538dfd3faefe4687f869dcb3f9402a71f3c15ce6183c654fbd954b33c68e69f7d8656225fb0a74ff867acb831ad6c5d15859efc30d11687b7dc7d39fec634834f352a2290d37b9964b6b5361a9cbb80159eb3b926ed5dfe4393da14349a9aaa5b662adff8e2b6aa83aefe50cc4d3df2e768f8b3f64ba7f70430483c21010799936567d30fae187c237ec4d8bd2a0968a9a3f615a44c2dd32696aaa8707490081146ad5e168ee40d020271ce7c7283d8f4557247b264751d4d17795930c8e0955f5a7f5d343a4cea210d41fa54b71cd29cf833dd9d7e8ea24850b8a0006de87e8ad62273c02929f517d49a4e1725a28405a5062ee42e1b3694b0b3e86479c711c26094e0d32a5642e2701ff862f1835e649cf4d4b715e975e734348fdce80a095be15d74e212fbae6f678250cfadc78ca5d7b7ba405147204c401416269dd736d091a8b882081be0a186ed8379f64401832f2f725f82e4a6618735075aef5ccc6961b6c2cb38b9582afbd32212ae01b9e7a445b292fec5db1b6701db23198ad23426ef89bf2b1c79db4b403e5ebbc59536b54460d3ee9dde1fcf7ff6472e6240c267c54d7e3bd5f2fa104aacb26f41bcc60210535bf857249d63cd0016b6440f796d81d103332ad6bf57ab68f2880ed8880b2db3ab469e5c5572de352bdd8895f1e225fa6b97064aed8599dd28a65096489809451b81f818e360f6fd024d5b6f11d087a81afdfed65724415639913d91d36c01246ca810391d789742c3f1f8f287ac1d1a72643c4833da73186327fed606ff3ac42906cb0fff6d9090a7771d2a29a6755ac61c05ae9a51b9d30f74398d685e2520feecc23d3fd5f3e2aa199bfb8b6ca5823cc6ad1d10b374d4ecaac44663b32176c393cdc9e3ea8054c7d630f0b1536a0fc790b08ac3e648cbd031a884c464ed721e0f2e9c5fbf90b0e14355d030e247e6a9ebf99b5e49be1a8df8b25b4a0f75808409aa3eb9032a0ab9b9ab408fc9114f214420f11dddecc928a207b81699edbe6606018b9e6f38eef7b69a12152645ba23b81001d6cdb944d87380758182a46b491a86aaed4c5f0ef9c079f4a329c226b53ea77a031f7160ead6dc56920558a4d0028fdc431174c65e15b94963ef855065fa58737002ca6a0c1fee4faf0fced288207851bb3a86ae21fb8ae6b242e1c9d742a906759939100103bc485f71b7d3c44ab9111b8170c1d5e34ca1a38365bf9cd4c1249075a6e6e671bbaf1fc1fafc0235c3e4789db363ac71f9656c0c74e75dedde4fd4254b641227be99936987da101a69efd3f54f33cb81407220b600571397acca601075c5665442e504cd55301091874945c642ae09cdaec58ff36677aa3cbb09db9e74b8318ed25931cee4eee08ddbbe221eff5dc50d2a9fe0a6e74e0fdcac12647aad324dff329a6b646594540e5506ba055907a6f1d70f7c2558de3be3192ba9a1403dc15787aecb9af7f2001ee5335fa3ed046f17ff32bb62339005a1fee0011fb44a76cd1d9d1ae605043bd56655a83aef7ba9ba658fc4c9d22bf374838aa3b0c9ff4b2631a9dae8efb08867134210795744ace79f34cb534f5d14e7651c97047366f87e987e2cf3c8a0580b4da1c650f632a60262acb95f7321496b653f8432c99e794c4eac5c2fcd69aacd7678fd561d04b1150258b4c19ae90f75f8afa112dbd368bd391fead712e283f56f62604b85bdb165881d73294249513e9bfcd9712ef9f9b3b14215b2c44b07d818a8de800ef1080c95c8e40ff0529e93aa9e164e802c11fb1d247ac563501ffbc144c0712bd232dc35296ef7aeb5e5d7ce360b58cc4671daae14765d3034709152137e9f4ff34a15602c9649138fbe5fecf3e8ac2a73c74ad505b8d977164e8b21737bebbd1230f3bf8b63d98f544d9afe4125e88fa8c3a894243c64421854985da0de36ba04dff5b588d380ee03c904c274537b63a133a339237d286df2e08d0defb496e2094d3bc50932d10a559a325e5b454a42dd3e172b3aa29892b28f0f8adbe40dcafe82bbeb4ab782137aa9f9d427f0df4f189a7e3fab5f6226f35822ee35f4b0f019647999db71c3af96392acd362d45ce81fd9b31769728393d7b0feb3772bd4c3cb2562bd1876e9c3475125ed38b1a65b06b31d62879242227671edf0f5f8876fbcc4ce97df65eba8c414c40bcec3ffd4e43d93749356151bbc17bcb7f6aa1fda62884c0626114cc6493922ea16640034aa606d0fdb7b1854a8d827edcc78dac732907dd3a84814920fd5af89dbebbb7da22845080c9b6b3bc788c2e439c755e3bd2fd73e0c0ce2486889df2bb010d7bfe6c4a6f215d10fa6070795664219ccd5dce1b305d94d9f7f7cd9012790a4a87c3a4b31d76673dc0d612bf7506795b3f1784041bd80cb832a50b4d159a40c35a59607113473a820861f035bd289b690b96219382266a87c3a4c7ce115b927350e89184d89a0d8f72e0dba98759440b4b759dcb60032c4c831a45d0e8217b7bbec25c12696147209d7c8734661fea8da45b9967c91f56412e81d20032da277c4509c8974bb1ea0b52e30f9ff9ff361c2860d783467da68d0ac8cb23112939fd68c9f90591a640b4df745225c6eaa026738c7e0f46b8ff1d0359650e79748bbcb54a1ad17568d704f3d3fbd05e01d018476815991480e2f8322a5798e28d7a3df8a14250e1607fe7e5ee5079be041d6fbb084c4888d4e66c16b78fb420db58eea8bb67e407b33d0404e396a10a86000a7a1b8a901d5ab0ebd4481972ba8759f1d3ad2a25f06ff6b4e3937fe8e55123a9c034b2636bbfac3e530015bd7e112bcbd34f6b7f099087a03f60771f39bad996def8d94c15da4f64a15b8d8076bf3911e65491d9e83603d819c1344c57588a7dec7e14bbfc87fe64752ef5a0d167e48f06367c10d823b689c99263b579718d90109d340c7b73a474056f7278dedb697d8bc351115d7211f584fa860196ecdb0b56019cda01da74354c5e700cd95507dbfcd00134e9a1356ae0221b80d382f79088453381d43cc52416ddd933d3c8e837c8ce87c837ee86c8ac9c582e344e43095630263ca20612d45f76fa5580b722fdd05171115f774d0d42cca28c3922cf20cdee945252775befc304b9047b04fcff9fc29e99f9bbfb893f47f660828680120830c4b301c0ee04bb51e42e8c30bec859a1116f1676a0702a3dbe2553b90abde3122438b0114130b7149dab1c1c8a0eae44cd4b04f0e6e20912dad4d8a03a47a19d0722d5b8ce18824def683a76eca1e728c2b62b319fdfd5909c1fe355131c0f3c2726373c0f3e38261bf878e0413211f678e8d198e8f0f013f4a2040134f9efe7864d77f71fc51f503fa4d2fd09b1dc537767a292aa9eeededc87f4bcbbbb0fa9eeccddddfcf29bbb7bb2baf3f27ec0031a1b4ca44ec8cc0c61ef16687703a13265a5d50cc8552dc8cd946dc09d2055fbffbffba63bc3909c46e1b1bc5cce68f2d5ee7e84e8c811ba7b02cadf2a725464c8cebebbbbbbbbbbbbcb3b54fc4c064d59499c259dfe999999ff5967cfaa9cbabbbbb9dfb40a9a59fd76f7c65c83f791345e7cd2dd46702c59f9cb4cc8208a27a999b2f2364bb2bbe1fd7d1c138e98db054c43600670c486a3f16e3e201a208b1991a08c19d2e7943384b863849cd990a40ba25fa42325ad7483b9216567ea0098be87a8706ef0c068caca2372e6419273e7b24a26e0300a6a7ddd7d779e8b8e4c59399c1515bb7bdd63f8aabbbbbbbb9093292ba3da083bc690e94c28f9ceb2bbbbbbccbcbbbbccbcbbbbbbcceeb7222075997959cb315834930aaacacccc2e66a6a21c95dbdb64e998cdf5ec68bb98515eee22d7094a0193d74b26e1efcfd7e0ecef575134af0e327f309f8f19570ca3cf841a94e84342f3481b37e2088368b8e03187c62668c3dd664641b8590c5f89deedc83693e10bca997d60b3991d2561a090b64acf367737d28b5bed6edef284ad19c5f262d4d5a493d977d6eeced09495452807b123e5eb3717ec7f32c55762ba29535682d051b5f33a1f61cf337c103c45988d87a0e1c2c7842a60cf09c8a65c146cbb7b07c4d98089171931554f4621aa116c26c082be500c732070c01b36413f722070924c4ba07020724e3db41b9e9c9f0dc50810394705d412e983da2f5ad4ffffbf9d292b7b40424447c30fbf22caaf231bf3eeba08b16e9d4d24444444744434242a124139ff8460180a9ab292e81465fc30747c16215e0e01739690d507a1abda6dd7fbb002e8b78d88dc99999dbbbbfb2844edf71c157325062369ca4a9aed4311ce8d6cec777022c6dddd6db4336565ef8311903bef7207469599999967bcb8aacca50981001c5d7831a272a6a89b9217b39a84eeeeee261eddbb9bd7a12c70334d315179069b4ebb6718f568679ea1146466e625aa25ab97dd6566a0addd5a65775798ecd6c191a8f0c14fa7850898125067468914194e3a4248a00489333e2f217107c89564db09fea047c61d1e253ec9b8d3a4e7411c8f4faf853c9e1724f80324cf8dde2ae1788a6cd002f27ece951852908b1331a272f87c48facde05991f8303cf6e8743ec4f0c96a89f44204062448bf9bca8c9c626de351cfc8097dab8787f341077c49a1fb9033928074021148315cbc60d460dc60ecde33acd4f46a374b2d938a54fce9c34616ec333327c17d12de7b4e464254931917389020e1d04b1cc4e49878e14326083048c3886502adf643372cd823415356129da23e1c31326fa8bf92eb9246ed149650e49086aa2cf0d6d9e58c2252cd29dd4c4555b5d7ffa672c2ba6349ab0fc9ab9af38f05160a51edee1d54f7b457dc634a92eeeeeececceceeeeee3402acb343fc58b2d203a023f462a497f9d3dcff520d1c136470c0a4a0e3f0c9fa5f23527f779b9b6dcfef8f84a15d844c594974342cce5ca0fec5e95d082487cad3ae4c59599b85b8d998bf9a1253ed89d7b7bbdfd10b64f86f3d2ab8c9cc36413427e904181a123ca8ba354932e47da794f5d90df0d631bdc442c8cb740bc26636c85b035e72b0a0bf237d6f22572916edee1ae2acc6097642f7343c173d2e43acf1d3b6e40c6d0979420fc71c637a6bb399d8b5cea6b1646557b9e899dd80553544cc626c55258c98cd048bc4fccc6080343103a8a5f0080ad286edb0bcd651570a529e778bb5e2adb87339eaff54ee0cc2d09495c51610a076bd66fdc7115e7aea2d8b180e8fed482773640892a6276766e18f26179a0695292bad5a685cd56ebb961abd978a0400530c7758b910011e81da2d4195f8141ecbea696ae9c9c86b297ddfa5a124ba7ef7a61f4d4cdb8a41728c63c9cac6ddec92d38f88d6d2ce9495bd6d59028a016d684a332d4c461a382d339c52a06b21462d7980dcb53421592ea8a5d0842569bfa81679bbf0bbbb564553564281b082a18b2c61c1c8d09495451046a08c48b1a02b841f7555f50080efc9ff17312efade5405c20a88223e5d773715096aaa32c182ee4e49cdfba244ccaed35d482a6eb553d457b09902c7e25dde05fe93b3857e4e5bfca9b9bbb337378a5d7777239980a8769f3c96115a8d057d19a1b85e2c483ccaa79bbe326470b2ae7767163abf7fd22288252b0bb06b91fb0dd580e8f4e88afc8a7859e05aa8060e2c9cd004b4a0d1adc60174ace1c0c2c661853149c4f2e2475d450c6bfe3f71d1f71f1588a089b089c0a9ec3098212554545a01d341958f6fa8b6bbbf2f23c16052810feffd6b565c3841be33fdf02e9008da9c6fdbdabb71257045bd1a461cbb8bad1e6d87eeec0159b2b27158a7c9805a26bd2092324af54d1678ebff5f294ac9a8745442c286b8f8efee16ebaeefeeaeb3f3fa361008063e937a494049424944ffac1f10e0521882320ae146090b5974a1c1e2ffdff9938057199c7576d271446aaec4863c18312a9831e178715cb014c4d9e13131914001a05b9ce6dddd1f5cb7ef3623c8663622285cba29d66e3ac4e1128b302154cec90c1c0fceac974c8a814c9be5c5a82b49ca37b30d2953564e5159cd6c5cd56eae45f793a4809df48da3292b91b31b496761921728333fd54c5979dbcd9e7accffffcc7bdb5d1cb4caebebcc82a2ec58a6a8987d76771d413a7e3a803a82e8fff3f3333f7f8af2f3f3eee348a2cc7420bb2f6041d1234c33923438904c4d2e39331c41a4219d45010a774e28478476f77b8f9397bbbb67ca4a2021f777de1fce0b63336525ce030cef1f013a173dffffde1d9870facbd19495480f2fc958b7bb3bbf13e97325868b62c9cafe24cbcb3a5b06c894954244471e6486eeebeb4c9a4da2cdad76eace43307fa2c3e9dc776717023c5045522f6e263872581691ba4bd4f9ea32f3eeeeee32f32e0fe12c33e3184d5979447ac049323333ffffff0d3bba64d719c7ccbb0b0116df9899d7d7b995b2a0088061614af1a6b164bfa89338faffff3f41fcff77b16c82f829527c816e7e2d68804c2880395e25a0458e1f6f9d5d22a843ff3c6163c9ca269270a9c042e14311c44ada84756c25e673fafe2f7f88d44fcf4f57fe63ffefa104ee3f1d648e703abc44498180eb6043bee8a4ad42f328508a3b33bb9272b5ea296a737777f7ee6e777717babbbb2faf7bd02b3118a9250b5cc2ba937a8834dee6ced1be219241dddd4d73df5ddf751e01655b27311cae7acaec7bb151dd9797796f88bbebeeeeeebbebeeeeeebbebece35b9a481a8dc6e367afc480b54cf211eba6ccc0eadeddedeebeddddddebc965a59bc493ac9db222008b716d58892d398a5a67aa9cefee6e920eb0eed1ddddbd85ac77abbb936c56b593bbceee0b5381bc09810491a91b1827cd44074254014349978a20747fc8bf3bf1eeeedafcbfefee3ed5ddff5f6fda07e2e63f06413ff6b7f9ff97519f569f99995bffff1fa4f2a9ffcccc7f7677f709346afff2063660efbbbb9b620a831454ccbeb2bbabe257f76f15807c186770393a3f4d4ca0a8fbffbbbbbbcfcf4e643f6903e2abbb55d81aadc008a8861705b2bb45cd02018b6ead0d8243966650106bd49c08d2810150d2878d3140e1dbe521422a2f062792b018939db4d1db0f6596fbfbfb7007543b459d5ce7470c1126f0a66e7c8c90422fc4b047e3ec6ce4e60f4558d54e797df83a19f6d86aa77e7ce9b4db849b3f1a8da633828216af96c31cae36af3a2f0431329e4af8f09d208389cfd4d0a784a35b057a40291667a0daa9b9618386026c309ab2f2884c5bf8b7cea6893265258db1698eb01812f0576238562d3857b5db8ed719e9b53f633465e511d932936414db5d03fd9bdddff4fe06e86f84fe86e89fd55b1c89771daf3db9f94c5919d472fb91f0dbdd35405356065b6a88bdf21301d3da9c6037cd19bc59d6d939a7dda51cda8dd9a2c3e18c2cef6c30e625dcb1f2e668b09515b0b45bc9cc09ae5bc668d38233ae48fbdc60f98532442c788b797959696ae73697bae9b9bbbbbbdb03aa2e6d77777799f9c2c6ecaef12a0433efeeeeeeee099246a3e1c83c8b9993b55482c22541b06966fd68349a4f0dbf19554b2525b8ca519599b9d9c6274a458e5c2fc7da4d62090a573bbe425b0f6ad26aa9342458d9a49da0c5cccc4a4bac2aa339572228d172b0a01604a10d599763efeeee2e33efeeee2ecd88c267c7d0a24ea0ffaa18d60e01e5659d5dfbf1d3949ad77c41ba6f7777b7075b7fd212e2aac5a5e66eeeb8b73bafc5ccec53798906646666981e0c10bf989959e9ea83ca284b313602a0d8205dfbeefaba8d74bd12a3816ba1fd78d83a3439e692491b230c4d872b240e4e07264e3f39290495426831d32105ded42eed170d16fed141ccf68602a405d8d052022ffde163e6949949a031ef2e33f38f9a0096c69295cdceee1b949062ab2c7cebec291d18ce95d891e8cb48b1eeee06f263c9caeef65d71612576ac1d6fbdacab80ff24c8514b90a1d72c9988aacbccbbbbbbececcb4b3e6a292d406c22982961840d116884ae427076771974a9049fad0db0134e9d4080651eca9341cf4d901484d0e3e7066bc90b0730f6f947dca8512286cb8f926e07875652bb86c3db406e00f8dddd6d72c44d86dca4c84da0b88954cad68c75dfdf515ca4b8a5e33c763640d2432447c36151a8bb2f3b75ff7f2dc8711102b36f62c5cf95188d88f2026477fff6ffff2e5c01d553d8ab83a3fbbbbbfb155a036a3b61c0a72ab0d44286141554430750b4820b755540495d9da2342712582994144d510d281a42f04a3d455d8bba2b3d796100054d5b832b4306a8060b3afd74d174d30a549a601a98f535a834c1346055579a81062c4f61196860a668c0aa68ba69eb3573a52140d34fcf57065cd5e5d29001094ae06907d0576b5fafd7ab51576942e0ec3345530f9cd09c48e0a4a2a96bd3eee6c099a6a41a385132e87a56570668bafeaf0c25a8ae0c655445356055d7704273c200d650b6cad40cb2d8023f28cb3c4d99c9b504a1c6858718b4a3c6725ae652790a853cf548da9082290c504ba4a04bfd5a0a7b18612d73f8328114385efc98616203c8816b78c854de56cb6ef410d232950ed0a2ba400836a9282f095051612aba2c4f24a18daa524ba11106cc3c69f22a0cbbeeeec216537553d4d61381002d1422e2b6669703aba423554156e868382c4ddd9ae1b2f7862a73730b2253561e0d8b50b58514ef77f77603e0eeeef6054d594974aabea8f6eff6591280eeeefeb1fab92251237123b1fb0ab9a25cd1095f7ef61152a19999798868ca4aa728e3b10e219f47f0e5cd9d33402012766eef1c6f77770b5f186ba7deddddad828644d3a3e625c78baad30643e74f1876778543495a2ffb0c5384298c7553f724ca8b929e5d19e08e11d0dddd5d767616fa04cf6e1d12ae8accccec73c60881c105286179b91c55e238a07048e198c24185f6b352901514a620a61f1310c6148ca5b6991e349e46e89960084e99a3c736b7520d0c2f1e351e371e3b1e3d5e5f7e2fbac0eb72229ab2d2a93a45d15c00836a9556bc501d443a8e740c77ff1ce49c863c6e366ac0dc9e6a0fd8e1cdade47bed37f14c59e9ab4d4131de67a5190cebeec21090b553e6eeee661460bd12930a4a11a59ca4a2a48c3aff1e8cdcf81985080145e0f0b5a5fabbfbffffbfbbcd4d82caffff7f8e618e620ea81c5239a6d6d7ffffff77f77fa12cec8d1b37700c87b0968da2292ba1a4a6aa0daaffe77e7ededddde7e7ddddddffdfefffa3e6934865ca4aab4abcaaf9ffee36f7b678b16067d7189ab2b208556b48d9ba47e0a3096867a9ea85120efd528cb13daf8f50615384205356fe80c12a02d15d06f8ddddfdecc39ef3ffffff9f6efcb4e3a79e0c07707eba279b0750431cde85878cfaffff6f53821743316058219980b8e40097995fe110e7dd3d6368caca629d017501171c9410ee30018f8f52c8038805adc00d8e1cd711affb7644cf06b264650b6f486a989959864f46102c048d9f5d9370361de4d9700c228aad419a07302d232290775621cd29c73a9be6c366d60f7e426a4ef8569176476a9899b635860d96760514cf288d461391e4a76e394c215937459deaf9a3d1682756acc478b51c56e178ad154962f4d9c364515864fbdd104a754f9bdd1035524a10617a18d9aa8a32be33841014ea32efeeee3a3baf7777af27515a99f2d56e5a7777b757a0112b98c1f272397aa2023fcb867e8f0ec6e64a0cb8bbbbcbae34f302e33fe94093dcdddd5d666666df9edd3d1142a82e3373b3b3922dc9cccc1d66a2dec65c43abbcbbcdccccb6caebebecdddd35b8da01e8f16c5eebd48d02c78523d2a11d6a3ea69b47daa8f1a026daf8ec179f5167230e7718d18131da721d5c8c223ac4f038c80997f4a8048b3669d54d1804331a00000500180782208b522a6d0014000d248e68a8dc7c64502a9248814038188061208a811006611008e22086a3301e576b057d7e1c64ba4d933a44bd961ac1b902e4b13f574e84d967155597ae76d6b22e94d15bb99e884af44b9ba95bc36659f77e9fde84fcc68425e78b61fe5c86fc50b9d9d8810787d2ecbd3b777c628a62c7fead3d89acb0ef4ee8645d4bf50f46cb62eaf3b0f9007f0ec094ff982574933ea71ec39e502e21828ea9c11b9531a16dabeefc67f92960eded57644ba4770f620ce8062f1d0e7d76bc64fa02d6624883bf20ff040ebaf09f7cc25a1ae92d1ce974c57537e94bca0ce90e1ebacb652092bf0f925ce3c590eceaf077ec1f0b36d9b712f3d86b41588beefd181dbb3630f5f93e2acba1930583933ae94787c643ded0d5ebba8130bb8337e93f9c79ddc5f5acec438d90a86328486e6ee5d4a4bf2805d88340883a5e2b28dd65ff1c65bbd38188770f78c02edc266df737ed7f0f3cd4edf40d746c71cfba1c2a5cba659ca18eae6157eb2fb607aec35e64ee03ec6c3bc6e9c901ae4e27c9375eb1d52a8179b057142e7cbab894e560543cb23072f5b5a4a223f60e15f51649e0c6e6c37704caae4aa35b4da587fe3a094e782df682e1b87e9a362c5397bd03af5209f902f4410b51351d27eb788b362b84968d96da3082534df3413bb427ac49d69b186cce9306a0aaed75b5204c20ccd31bded57efe27bfa422d412066bec76a4ba35054ac5f9ac319ae8c392b8ad9494562cf2009f0b905392a8b274a5ac53d9623dde115f7f5a285394f98f72d4ea693896e259822f1242dcd43d21f7506f2312a3f2553a4bdc366857eaea30f6a4dd88aba18555190cf055b333282e918b468129e8a953a4ecf24a495b725985a5eceb93178afcea26d26804a23148c151f00e2b8e34f3b1b1dd5500413b2987291188c8660cd4c6b5c3098e8a45b59aa0cadefedaa8a93cbfca72147a4c156ec567396ac7507b98c73d6d08af7927ec6bcf2db9b7177804a7ed40d49777d45070247947d42c3d5d21dd179fb2c8a9e470da73897869e042239029df490f04ed5c2220a163f4c2649761bff003846ebdeab9681c04a4574c45a8147c9da6990d1385a41f0be121c6c8d70d65bf9c00fcd8a36aa6ede819bc721b33aaa74ab6e811c81aca56a75b7b6645d64fbe2deedc7f6e4f6fa261836decca51bfb898c8dac9938994783c8f5fcc1c620686bb59938a7f143f09d404c736136929ed8783c8db559af35a11b9cc4f8632fb2c67bfda962d508e77acff4c5ec071e98933bea90e567f43b6dcb9a2b78f509bf6106d8de46e737df13cebf8a03cf38ce2005ec9539272202d2f38fb7883c4136e34c6d4121e4c440c780db7a118d2431bdc64f79e072fe34e99d9f27dafa36b018eeced60dccdd709e1d0682c5cbacb01882f43b370b71360396a5b26825691357f6d0cb63fd173ae8dacae1fd6d89b54f713f7a1bcbf87e8b1e3a384a12466d4bed50ec7ce205e5b9da6bfb18c47dd5f19d4c45a3b4dcdf633fe0c823b57c846ac04466e2772ed2d622b2c477ea54848d7f42c41d762dc3ee8eb82a060fa0905439c416c2c00804138105871c8f05a8a4ded8563b6dd9f9639ca4d4558efcf155bf6aacf84a06597ac6192b3f670e5c9ff619f7376daeb4b048ee97d0aa52523263afffed1d42a295519afa23f7cc0c50a49c76408db9ad6c9db99d87bfbbe9b224684a1958cdeb63fa0c90ff14b74994e626ef0ba91bf9c80440d68ba8c862b4f8cfd397852f4361271a5a55961ac1d0e2ba7abd492943971604a42e25e7cff8b906e343d0cd6eef1aeccb2d6b189341962d0f2ad1f0ed385bbc96e73adb4001198d0a55ff6a1def1f3c5eba8f34f4f6e93a03800921b7d362c58941265152a61f959d0651a02b001ab40328188cd7f55fdbf7c119ebada61c1d3f9c37340bab8c527fd1d86b7aaf4d68f8571c3d9749741f6c11161b0010a7fe1c1831acd7ce3a8a4fdf0856b318a067e02c6f2a4893c3747a50e40a7c9a805a4540a76bef7eb42f49d6f99f7a0beba21d418a46249dae4f6068714f63c29c3816192de80450d65f994c45e8413b830fad9c7fdea24edc64c39c48f48511c938e83d458525506f9193fc84d4b021a2009a9f488ea96c09f29f28de5a292a27664fa00c17c10ec3419af08df7c41f26ac034ee16e814ab93e6daacac6b600116850ab254ba6c2d82ff9638d6e8221f22da94e82079d81cfd89c99d548aecc0a6bebb82423807aa05d8c26b557741659b1717d6ed110155f818c350c8971637c782f0acb005031401d6774bc0cfdf9649550218714eba0908c62d60e2351452e45f83610252a43d0f857c3a6158a52a8ceac73dfe0ecb82416f9142a6b8f53ecb0e94ec8ebad8732b5c5246f196da3c84db95ef434cecf90c9d41910ec7238d796ed0e292022a6679cc40b47e81812fad1e15ef1dce9c36c362ee16d448db1863e427b6832944db31a62f5e0ac6107346bcec9b1802672be68c79df71bc157346d1a330805f0caa87654c333d518b71ebc9105daf17910679b83d4aef2c1625946d2fdb0d6f2ba791a702670642ce774104aac343c106642df3e02997833a832faeec5efa383775ea5b5e2b9ecdb3a446cf2bca3be76baa38185f943fc3876ddd24f65ba5d1807d5fd8d91f99345f918f889a3f4a2d37b087e3a8c52c9a54d0a78ebe6f42c7b951ac02a7335017aabb6ecece28f474cc7245956473cc43d5082c3eecfb10722db5c195aabee948b3f97d7204617d60306ba172e0498a58ff27f6cdb320cdac278c986e3b27c2bdb610e0efcab76e48e939a5f924020078bf7282b0f6392470aa88cf123cbc154c7571ca5b97cb323dc274bc89b9d052480d97a1bd59dd894d97cb76158806ecac4ae4bd84198af7536d3c4efc8f4f245fd8f97f041a65c5f7da302674dae2723fafa1746734772dec1cd2e5f2c2dcfb11473f8f35689f764d8b696be25f4ce54a2122fa5e5721e6a36e74e0ce22581a6cd2852b0877220fe0e927cfacf3450a576da3c52fc1dc0105b18e56b5230ea316121d4f32116b33d2c34d7d2e6141888e20f96a67934c28aa236778264569173e0ac7e56dae2f91f8fc2f5f051064d42be364310995031ce3e21fece8e6a59a451ef6a534fa166543e504e876553640372719c4882f2347de7e45d2ede295c528686b19590eb7486c933a2d3ab28ffb212c6e54f0dd9ccc502c0cd0d4b9b42864e8f1318f2e8cbd58709ab6638c917735e2db31a6d8cf755b80b74a0a2bc00649c0ce56b58bc2b346f2c0d92d4043a6675753885d442e5c438c316eaab825c82a668dd9456ce9af5f071f5b5aac7a521583eedd6fcc3326d9b93ed047bd5382746a8ce755661cf10ba67f1dee3269ddad29b992b1c3f57a3c082f2c55a408a057082259aa6aee98cf171ffb852b0f610ea59cd06125a014bd7106222e65132c843fc028429ef87d2b44e36174a8b21c4822338e5212d04460622f202ddcb21efa2a54f5f10c18c66f88bc10d35e3db39d633f1ea2d00727a58fafa56146260217afca81e4a097e769c970e6ca74e488b95d52297a766199b29b08c36501ae8de2d05f80054f310e88cceeb9fbd6114d5ebba0f174bb10a2f246493749069220d22daee398ce1762de5074596f6936f93c30b6a82c1445b62f9dde307634ae22209b27484a0db6939fa0dd1b59466a26e00baf89446996a4807aa97bfb9586032b2b00928a8a9081601638bd8f356e25e861b30df7a429056a244a7a869015848a82a8b48c1d14da0b81c6398df9d352131f444664e0b0c5593bce5922b52e99d7e572e4286fdb1ea838152796ffb48113a6e5e495bd2e2298ab6dcbe8248f45555cf2b932db916c48d1c020eac3de145b06037ae1f5a5718b92591b741255c0712e681000d37d5066ec47e224b1e3ad56e9df0556f92eed6311596b0f11fbb30e3bf0cc97faba27ba8cb4a2644d709d6231cb344f65d3f432eefcd7c8df8f5631e1661a337243e2dbc98833f858a81e90819f071a0427823f91edd95e111cd79251d418de3266150ea8c37229167b22949f50a12aa83399093c304f3e730e3916012c92ec154ca4c3bb7ef1fa712401d4a3d09c7000fd123715a550272f493d991b9844940d2ec717a874d18a42f3e28fcef739329fc2e97b403f3924a81b3258856c11bbe5287b15cf5e59893a876146a353ad63cebdbf126bc394c088053b58338bc0cb75958b6c55c0b3827b9e276d8cf5e5491cd9d922a6a08be4fcfb23930cc99ba53aae7e0e9b81d4cd0983d410113e68d63d01e47e6182085eb161aa9b0bf4b9e8c6eb2542104df0666f0726d2dcfcb6f6f06550c0fb5b4c5acbc867ee2afed42e91a2d4bb39a465800b756fb6bb7b01b6e17af09728dff341435f16214a8ba272f195ab1021f1dac81ca358257746927d590c94d4f54e10281e7fea8a29f8f70036f598bd255a13c2afba19dfd8654b92105282a1c6707adb9e78d218ca81e9d8fc0e845300df31caee77d70b481283a4a412505534884a2a346b04d439c8db59b796221781a2880ba735dcd7983a5d03490ed23b73df1d6e72c0c053fca0f4e73f231245a02df1d3b1339063f5fad161ce059bd00acf4049778d42a72643b768977f22b7a0e3d8f9d5f92a937933a0dc72f3a22afe6b2c947978fe386861e63ebd67a9af3a0af403bb1585ebbee8c5cb97fe69613b3cbf3807805c226b6aa55fd83a4f1b97822c02da91fb0858e6a105b2f0649c0a08c8352171c8987763dd73d7b782ce0259dad508d304ceb7a78cb291e0b682eb173aba5c08a37008f1a5cb044294e524d03552f289565d5af5a1a0a4fc8bf0d0e84f62dee4d8a4731cf5056a540093e4dde8df53f5a6520de3277971eb992a21bd344820ead9eb549bb4b41228118e86881e8cc7d1bba7f651d5d270a8bb0cb8859e33c10356f84aab6282e3078efab3f0348a977e9f70a219051600fe0464547f826a2575356ee231fee7a80e130877b3448ca966906e1f31266e22a0bb8f3675014c7c71ee263438723c281e79c2412218275bced40f08011d05dcfe4d185329d81c14ffc4ea268d507a6f85cbd9485779b73e3a65d432d1b415eeb6b32b6638af5c56e23709630ab9ec23d1e8c1c53f5c248cc23648a120df4491615f684396abc6f0cf961aecbf763e5b6c815b31f2bc9791d5cda071d56827d9eb140c92ff1b4640e38ea80c4322970a0ce6eec674cfc91545c705ad34963f5557b3285a3db346f08c0bdaf824d733f23648d03792275e7505d7fd9a44c0358451323c1b6c5763816ac588087442e59c88ebcd7cba1e525c4c836043cca831740205d70ec6196f636458282e15e3a60feb6f53b5ab68cbe84b8fd72602d3255c8e06436541d3c070f90a53dd984110192aa1a68786c04853bf6a4da672fc02977672a920d4899da9b21722d75859b912af2d731becc665da4bace8795f2e07dcb297edeac791845c1da652de9b645341e5eb2df957a84ce233fb299900f433d91e47714b1f4ce443d89c36cd24d462bf418c30f6a12cb1e4599eee479025473e582ab2f45a2f26b587c6570ebca7d424c37b636b567431472d94e330b0dc22f39b45c568098ed23e93c6e8a1b2c75109c76d71769ec0d1d0e9d46690213f8a0f8dead785e25e24a2c6269bd288ba589b303964f2affe6e091a9c19df32e6b20c38eb30c80914973f4bd68f9b8242648562f04f5bf039389eab7a39f820902c902080f00a70cdbc2bfaab1e0818cb69849b5414014f0258658c3b89278905d69470cc81d156602860faff5e9fd788a13c95726aba0210943bf1c6a6e2dc9769de80391a936663fd9d6b7cbc6505a3b97ffcc13311d4cf4d67b522c723f2303700e30387140912352fe1ed8795be896de5a75cb346008f9b59433158c816064a4ae71a6a240124314d0df2b1bdc761b051f1c2b010e8d1826f135d672571e1c59775fb669a6c15a8f8467ba5c65bc4a2d5344178d523960400d068559e9b94471ce588fc2aa7b6efb88987d1604808c19b0be7a9bded4ec54a4ea7d3ee77228c697e89b298f1a1a87edf9f5dbbced587bffb4423a949f8d17b05e8eba28a65ac27e8cf20292eee9fde9825792dc4137005ce8cc0722b99e91951b8696905f26bb8e664288f3ac1ce69813fc89892c613293a85e5229e5a6421481961185079570cb58fc7a8b2f14a2a1c441a5f4c63f96da3c016300d26cd6b0bf6bc10321066abaa701add0af88527d356cc11d9b608d531c9eeebd39f315a6bb847c09163c9327ca39e16131955545c3a6d11c9860c47fd333681c6922b5506bd671d3d7397a10ac2cb9a64ef3e2348a33d7a49d8ba7871cc9c870f9b9b500cb1429f6d7d236310b4cb509630c3393c594f047aa8d0689aa52262c287db4354d1cb587d09fcd9cd004da703d4f59203ad76aa45ae65bd3a6ef8655f75ee3480554f37041c3b31d2de4c8677ee0697a977866fd9e92b72293cd709d5898e8c521d9f363126d15bc8d98273160331b01ebde61c8594dd76dd40966350cfc8898bbe0a74b8cb2faad044eb6f54cdefdc2984532d1d3b0595b1a0c651769f9f49018ba2613ca3a1ccdb63bdca74938eaa7c33e12588245746aaab0294d7b5d48ac8801bde8d68effedd42e07564946038d119555e937335dc9547e9c25a2983a4bc22b010959dd4a0ad276d399a414bb20066fbaf03d75cb92dce340a992bc6e5135299a6cf42b23705b0676178891b144a2981ad22a3cf298e77ecc895b61bc8d0635037ffb274e5dffbd42edebb63ae2d8c77749f1b51b631808c83a52053d19a09555b6297ed93580d46fd7e32f3121f26ac58e183dd35bd7d78bc36b513aa0322af1f93d4f81c422eba3c1cf7757e378d8b27b49712239431b16d7b7699a227e2aab7723d7d51cf171fe867d2a19594ea024d607a870bc577d46e9915871f4bef48ce7db77267ed0c2b41e92a7cf275a8c583c291205b1808ff1673dc2e3baa44c5b9b2f7f263993f3eec4641a592daf00808b7d81eff14b92ed542bfc93be78802f15ad3004a8923cbe0bc14e9b7b23192ddecafd2faf00267e28acd718a86b168a86df0c2ec8bf006d7343f0db1ca387616a254f807ae0d6f985b597b6809f87241729f27e720254cab609d90a75c30d3b57e3dd4fc8be66a3c3a51a643e4df301f325fb5bf40478a7dbd8c704a1720411182e98d7289c6a248af3c8db65bbe6a14884157d5ee0903e95e0d024f9cd612f41a4c8ba11345f920c1b8b7c644b6592aec044750fd419c88d7ad648d7788d028104d8d074b8cd15cd63fa056b4f9aebd7d0ac250a7b04bcd38f7d71e0a75f611b946a6c50d2921dd1fa69ad098d13ad291d3e7baa904b89bbee5b1690f712ad69a4ce3b871c3ae2ed0154ef5520a4a5e7fdaba71857c0abd348dd8d9a9ad6193f7411abf867d7b049e3d8b6784dbcb1b8fe44b4f4d710076506886b7a91b1895988f1c9cf3f9d38804890b23c400c1430368e79be819a72606dd9f1805b88e61281e7d8c5f3b596adf1eed18fa07801f01296e041713f3ec43b7c2581583ecf7e13d8cbfa61426f8cbff9e9dc1d40996a161e15683d5aeef9df1567504c4aa1f3f4e6ec9d43eeb2e9981baec9257cea189991f9672480da1a3f8279890f68ca9930dd83d2750b881218ab158d9ac2a04f44b90e4c4f87aa055fdd06b61396fb6387206d94e066fe995e71ab4522aac867d6f41b2607f3f21d9e97a0be9ddca2d5898b3dde20b9933eee461adc035af140d59cc3359d49f152d3f7a3553793020990f434a02dc64be5c89a5964fbec803987f7e6eece3d89f1224ea2023eb198464b0f4a2b9c7229bd16933b9b163ba869432203bb3bfdeaa75fa513ef1e36d24a3f70a40ad5deecaa84b7c6f509b9aeae72c97dd2fdac218cc3983db476f6964d351c1dd8cff2c18ba27d64c805eac046d3579cd4bca94f08c9ca934d65a1643ed323ccc69b415638ebd5658554cba7f7df4478cc6b23d4fe974faaed26833baf145fefe43a2408c58997bc1c81dce3c08fe01d56fc520a9e3df4d0aac4b03c24ad97ceab3ddd1a3213bb58b281784895d8ee33d15982f1091632ebd0c42894a2097f153bb4aae2e54ee0bd5ff92cca4bd2d797c314ce018fb6217b5ad43d8dd69592031b59d06a5be6fe2b5ae851ebefac5e79a6ad3b6b1cf4da5339883a7ceb16ef415285bb83cb03b5f8ad1442a90855d16fb1026e4fd311fab3b9542725459af1f6ffc52aad0295588fe9945bd6763fbb71da5229ae0e8f2a2290cfc5c09b1720d4ddc701b8cba4e211817b6cb2aebf2314746e32ff59299b8b2903db4ed12961bc01d72ab06f139a764bb62e015b2df9167eafe665af9dfe5eb7e08f91d357633b019d9def7253674443dd9cc7f27d72bbd1c166eabafd021f1edcb32cacade0ecd3097739c3774acba693910e62aafc22c3ae1c00c41d53a69bc88eea90ed7a04ab9f551f91772e952b70d2868aaf33aca00ef60484bc945c10119daeb102ac41babb04c1440390a1e2c3c6ed7ad070d6612a1f2ac0ce6a0039172ccd9c880305fef2aeff03d17525b805b9e4e0d65ac2b0994ac33a55bee275376bf7ceed13a34a488302be59c2c43c74381d13c87f586e4c521fb8c408fbfe8c7731f7841fd09f0a151a4eebe614d2b270aab670b05448618401d43314d6d23d0c5547040b3bc2402dd9dc05d4cdc4722e686c6e42255481d487915f1cb76fc712a5ced00ad462b0c0e815627be30a385f314d64314bd1a449df58573f068e142699d2bf996c25782d2fd7e706968b06e14d701b4bf14d14a611cd860254c93ffcf52c6c8ded31fa6a015d1129a48ce94c3c18e88274d91a2d31bb5a95b8c07c23618d2dca20e4f55577e59fdc15eb4c3a45b3ee6b1e4f8ed290d0b5296dcfd9acbc89d7b40bda6442d842efdc79c9b1163ace9ac470465117bafe6c724707247bb004dda38137dafb54f23511d032d83ab344fcf75694c7e10f8701f974736409797e49004b1ab3454779653d93f11427953f8b28bcbcf700045061d073ddc49ac5304192704cc403248e8fe8c88a7eb899978b12093b5411cf4483a0f7d1888474ab5e03d9b71261967c242a83439a534b7c5e6cf9395a8aa60d8c2870eb4b5c25f0c8fa2d81b2964e6d54c404b46e488b9c3074df43a315a9ab3126ad662555773da989281763611f0bb9ce6a3aa4bd191877039e6467eb795065b024293738fad76ed821656c983e4094eb3960f4ddecfbe46fddf03a5d3a62268b63d37db6a7cd55b803618d47c9bed96d5d8811bd37765bd7a1aa6f38ca2998ac811159f084502548c5b8d07b38ea9326c112aea441094564fde82d8a76d59b1078ee625ffa5b0a050f47015a19e832a44119a3fa40d8bd651cc0de75d2061bf0a9a715917a5185482c4926549475e3dd9114b2b8b691a2233e1331d790f37f44c8f40991e7934fbb4e35ae1eaeb7823952725d1d91b87486bdc3acce36e154d8ebd96a9185ec08b853325522b96b2c8b275e4f15c3bc6e10104f9ef0e40505551f3b8811c425e6a2bbe63d52a33307e697c659525f2121b15a65d156f102acc6af8362aa03094c871a7b90a2e9e7c0fd544c0c0517ffadd38a2db4aaed822f54484a6c5af26785f87572ca5d9b03cd574bcdfd24a45f73b178544c3775c3807f31b564f591241517fecb793d22802690eb0445485b834ede3dc69fded4204d19f00b5566230ca56ca69c86cd8a6179d63830568b1c701e3f2039f6173a8c2123c31b56b3671d8ccb62cb90d0102cb582ae56ee59e60cdb24c24408af979e545f8a340bbda752dc45e22561db8281d39530c7b0bef4cd49a5f22d189625411392bc551712e5de55fd365ba8ca4a3a32072a9267bd4de4090d718383c997a5a27fa8f39482e8b605e1a23f01295a8845d7c05217a1fcc388bd2421a18db909522cb23e9e67909e48f3f529fce852a0e93c68118a4e0a8e6e5cf3cb05eead4a43c084b285a8c0666e174685b4b552f0ff65d9368a10f6e952eb2fba3c3e02d7632f5167d179f431e54b7859a3e306c202422fbcb3567efeb9e11c35bc2aa54a1ff84fe2f945871ffac6cccf898fdd6be609554db75602c2441794b969d9284120d282ee28297b730e3d4ceff543187bb9ffb0c07f237990a279cbf85922774bd277a7a2bc28050f5d40afaa292cce1405a1f2d25c93332460fefe3e5906001c1f13a564f83120cc8e38ab204ecd32e3790876b27494b482b687e2e294596ab2f0e7e978c4b9adeb8e314f94297c0884b2c732fba481b3e93a641290a0e5e4ecf5d0c29707142c2b8a418c2f7cc22068f38d319a1eb355c8cf1ce07fd0c333130bd43a5585c0a170acaaff28ce64aa70a48d2bba1174c4119a732aace9935713c5142805a92326c464eef0ae7f56d74b7c7e649f64dc8256e8cce5c234d0adfd3f35f79d7f3afd7066f84abfae402cb611adc4e69bb167cccf1c038c0916eb4b9e89d06e62d9f86d9e9c61178b3707add74af4225fdc31611fda012581298b09fba7ce0acc61cdedbdd7ff5d1a682b581698eb954a4fd0389d6660025cc40f5df24126b1e38c9ee39ca2c84618a75ae8fa3fd0aceca41a4ae22df8af7dc2065c560316a0e9823650bc725452f02f56d31e35f54afd2c4ca437c83d12b10cf1de535cb7ada343b574b2d80b61d4725a2f8dc07d2b5d47ee676b0cd88d4bd8c092117026da5f11a7bc1512ba4ee469b4753c4f58e6758a1d6f89ed017e4ddcd7f56548c60fa5b9ae21544282a3c7190e4c82620e5d42d5755fcec14fbb9054e807ba993e1512ccc59e367f821037a2856f0c6b71fd3bf22a35a39b81818ab2687bc66b255782f79e19b23907f4163549821bb73ec6ba37c1bc6994f0f795dc956e1bca4856d3fa6bf2031ea8031e68878751fd902ebc2eac287891d904936b781696d5d3cc91b40f2b160124fbe7003dd6286351e269c6d33ba13bbbff8e4063eeb4efdd301b9d80872ab801b22cb3315e7324344eeea70166d1ac42dcf0b06dd36026fa865072da53fbc5af9006414bc03b0776e380cb442bda5bc9130141c0ce46be9cb7d25f8b6f06ff3341718a9b8292641cf178a2c1465578cc1bf7ac14bf4faa9982eabc2c03b220c2bff31c1a5b83cf98b224219a6d43efc31a429376c85aaad54b0b0d9100e6b2c221394a756dced0c89d96c0ceaf4e8511c4016cac3e13b1f038375b784a44ae341b7dc7d8fa975446be1175399119c9224d46a900b3e7bc9b27f3ccef1ef960fac7a5fb26c852c4968468779eae45c32732ff72a665649675a30da069105ccc325da79d09409dc2c259b71a34d395b55b49ddf70f76bfb38797d20f7ac3a24351a896ce0797187eba3c6b77f2c523b2e3586d471ff20279d8af217269ecc0ca46748ce9ab7b083c904669d569af01a409c3f8f759277492a579e1493710430713c18ff449aab942f1d5d37c40e042657cc330054cf06f027ebb3021ab0c54a9e7fa142e6f314e46e60059649717a4c1de33d794a8190e297885c330a21d81c08d75408727e82e2a9f5b4be1a244cf2d0ff61d69cb61b98508701caadb87c2c22721ea2041179fe233c1ff3339ec2b872df2fef27b92f6aae34300cf8326e1cd01f92907949159aa30a3ba44929ebe0ca78e7537385fb7e8d2ea13e10fb434549804b9976a07eb223176a0d398560b21ca9dd7125c6ab60ab993973c7a7de7dc0dbdeb642c38fe5ada37f8a30f082d06b9142da9496213b16e3d830f85b2efb76e1330e546f0189edc8ce36796ed0bdea48550c7217f3d60b4f3e2e9db41756a34fa1581a3d8f9cec1d21720d1ce88d1efe1a48cfc43b2401e3d6e244d335b02fa4a0f80ae733292808439d3b55be690760646a55f2eb6eedd055141fc310364bc69f64a6505c6c0b805c89889dd9e31526772da3b1cb057883e24568091dec864a727b5f0dc4e76329306088a4a7999f17a3bf73ffe831ef948e588a322965e50a3a4be2366f12a9ea472256e4db3afd582758e8de625a5b9ff03666ae08acd1da03c7a641f1e2a67adfaaca5ca54fc04fbb33b0a25e30aa31a2c28cd82515f99d2d86da31baf0ece782671008886723e5cacb6f1601a48526ca6825da28dc595b0ae786a0b29a3df34a683f909f9ff93b4a51bea556e0224f0a1e239fd37bc09cb6d2e4ba5745cd15c09cebc5b1aa08fd87c2895ab9c530f776c506ff65eb17f1f3b4b6b9b7bc9db43e2ec1ccd4468de91b573d1747d77260099feafc7b01756530f9f50c972fa175b57bc5ccbc1108fd76cc2e22a83df1a1bd66bd31e208332f369c94a81fa76eded8c5a16db53c14a294a691f0b61a95521b08d7af280bf882e6cb7c950281b96621c2b38498bebba1fc73c911445b7e85e023bf984a1057a6948750f56b43f436cc204c7cab61cf1d5e3d817c8633d33510045ade5fe1726db2c35dbfcb6137c823520c5931104d51c55c11f032e408ce809e91d79f6ad21b3b570b2521c9ff1eb695cec679fb2b638db746f013a07a5a2ec8494450110b5c5299e74cfcc656600b4885d179ed02cfd6008dad6cc914df0184995fdac2b3104ca7136730069154e902d8ac65b21ee79ac6b2b5e77a3374427dc5ce54b65de8ae4bb059ce1f59b350af91b652b37093986a8f747c9fb0644f14cde32c7a4d1554bf197fd1ac53a9ae06f90068b402913a55232e9e5bc332eed01543ef712a310bb54172138a85c0372405492f575686540c03ae164cfbf389d5102ff4c7702075cbe9ab7deb974ef415ddf9563704ab50662b7da2ca1a5b2ae7fdb22c619bb19b69f9070d6b2e322b624752c93314e4d38027696e790eb1e79ac7887d54860ba5b9dd4b046a0eaa546b7f808b0bed87b647b5a66cd0b7942b9249918853a5c60ea5540d613b127a1906c7da8b3f09e84eae7fba11684f2910c58271d322859804d856cc1169f55b4028ecffefd9bfb22b75c26d22cf557b562e0d8cb98018638c11981580763ff452d8a6494f8f8f13eb86c72ee50b34b24b9e9f82b111aa56512621581692e69952a2ffdaa0f1d7cc9958dd914b49eceeca4f296677e5c447519336d4739a477030d59b1a8478472cbf28343b43647873d912575c093ce290ad1de1a0236547398e5a1849abd1f8eb9c79e8226ad5081512f2df92ecd02cbbbf8e4db65c9d43a56bb198b47296505e2a297399da8e0a7ec6fdb97865b93a5fa5d2175c30e260743340b71b3684f9c81e928bec2bf37f2c8bba2585404a6276572e65b13b6b0324e2987f7035da7c1aa18c5ee67c69b3c993e63b980864db3a2721a1879f1c9f7c17b27211eee83c55e8a9c8a4cf91ae5a222c61f93dced5497e30e8364c889a343c3ccca9538bb5b2a1ee50581ef9afb7083069a44888a0841ed9b21da35db0165fd2dfe8209140a568738112ce2810504d3cede0adb1ab8e3442d1498b57d9bec8dc3bc230d4a47c23ae3221540d9ec09619049213e03465a31196a4fb6667e8e8b560ca7e6f88b1b9fe6778ef693c57fda5625a8d444215b31c2ad9eca8f2aee58e473dea6bf75f7eb72eea718bb73e9ef153312dcd85c6084fda49104487382240dfbd85e9d9b02737d039e146dd5de092aed8cb22ced6828c75597a273f961d15c54cc08ad9dd1af456eb2a832b9afe11c5043348803af30a7dff8e7dea6cedb403411365985b48bb0a378a8feb7cdd0269a11a1e9c90992e595e384880ba0296972f6b76f6ba196b1f2b09028a9f1b0091e75f1eb7e5eecf4226d9b54cb060af528308de64dec2a4705baadc458ed896e9412f997c11cecacec2355944df1abd29ae5a911ebb5817a6976ec3b576ccf12d888dce2a370f07bd723e6f0b37ab04b3325b70d2fecae8481aa300a32d51e909c67d76414c05168d053381b6638cd1ad25d9b82e5e24912b94ebb5889874a3910dbc9992a741d274658a3f864ce6a00087fcfd989524916035026db8f0916d424e6904b48166766a8737613a15dd3ac323e86f4e266886e8bc2646b46b5ac491b2de90ea746c564bcf5c24591e7e5f3b6b369b5273335b16b88dc4a569b4f43b0d6794b581e4f8835da09ec8ce737231975e598ed5fef1616c199368c6491d319a973f9ea95b5164bb06bfbfb99196c8891f17453a60469628bba7d200aaba293f37fb2750651944384a8041277157fc4eb6d5a48e2a4ec674cda310a6830031ccd524558996d815a8958a221dc95a4252915422f92fb148c5aaf6632a0fbfdb8b0289ea02be50d0c0be04ad7a89679c15ab146f4e4df1874b3552ee7320fb39fce680d18eacb3ef65294f87e9dfc9aca73df392000dc520450f670c3ab6b89fce0d0de9746d95ca00a5845c16f511c3cf77f1bbf2f5988e853641e59137907f4144ee7093538bc843466ebd2ec152a2690a9d3c266b74b41cb891141f797b15160b1766d39d91390a04a6dc0c61d9046b3044f19657d60c5ec83f87dace6bc129f5a5be08720533b7940cec470515ef478e5a2c680be48e01ba33ad4359400ab1950ec09342b151540c29141b0bed19fe612fc4097a521afa509187274ffb50ba321ecc80ffe7e82b091f683ea0fe3fc334ee15369061f92805a5ac7757596d3e0c175c45b537c150b8a13776237b4bb2a54c526eb977bc0310045304fe395927877c53e410426822347739536724274079686a378962e0bdee730846e4508726f80c39686abe91168c8ee4f9d482d93a9c2fd111e4e73ca975619ace0dfa269a612cc7bfb19b07cdba1451fe88d1fc5c9916ee508ca6dda0299a96cd8ccb103a34342fd4d67e378f3c7df3485e0e6abdd8370ce78e048fa3830386207208d3421322873aa4937bb2e69d0fd3440e152a041d28944441b4cc70cb0ce808f2f3ebcf107e48c3bdf3fe60f8c10c31a89fee6cfd3cdfe343801fd066d2e47d7a61ebef811e705ec3d691af7fb6a323c8df79fda9dd691a86cec1ce9376976f7690cbbfa83e33a06986d7bd9b6205f5c326b182fa3a3a5025090d3b7f4a42c3be3f41d6fdced9032fc83fe2eebc9bfaeb874d2905bb56b0f5a7b96a3425a161973f016abd841f329aea749abcbe339ce0264992fc0c21e93502e2eb5e84f8bad46a28df7f27db4d9e40f924a161efa0d64b88c185bf67affaf478ea06fd3a3caf3f84ba61f7faad970d39af5f43ddd07bfd1dea06fcfa21107ed08518d4d72f81bae1e6f57f503798af9f0275c3f8fa1510bed6bf01e801e7f573007ac0f0fa02cac3a3a3b3dbedfe03ad714ebc4d73d7ae5d5d24714ebbad1e4f124d3fb0c952a7d19d2fcf1b27cf1276eb103768689637e583a5699a6708ec2ed19bd36eed24ce296ef3e6ac3aaa4fad5067dd37237973eebc795e18cf0ef4ec113bef6499b32e492d826508b287c4cf2eab4f46f56bf2ec40cf2ed111fa795e9f3caf799e5737ecfee6fd79feafad1b70ded1b0a6ed763967fb1a541dd7a57ef235799a99ac3ebc5ef5f10ab499f66c47c79d9dd7e70ecf9992e8d13912e704f778864eaa4f7df30cd7ce30adfad4dfa1d51b75c3ced79daf17aa8eba011cb3b6620dc1acc3414df082fa18ce1d7841fd9d93577dea5f38adec93a7456fee34bfb74b736badf56b1b18662d4b5d795f9f3c93444f8f9ab701b8355ac2ee300477a703aa4ffd1e50de3967fae499f3a5082248814410731cb4bb4c569f94b73b3345517cad2b2d90e2498ee48f9f33697e98cb08e476894b11378fc1fbe150922e43689dfdcc5f86c8259ada5d7e0e4804a5ce3f1c2adf4319e5998adbea5a6c1de7e93ef71ac77f97f3e583a5073c34074d6ba975d034a7cb4fcb5ca9d391a97edd97676a6e20110c69321d411aca18b17b12b62ebf74bb73f93a5403b1eed235a865e9415af7eecbcfaf353a6a1d5a024d47547f9a434bd45d660bfebbd79fe6344cda59eff29316bedce9440cb9273f77c041f9da83920c3fe8d7a1a4d6399f86499b2c45e85ea323f4ef3e5792b9cc413359e69c7f2c4594e4e7b2247f0c9e8b467035110112c68a12190f555f5565e489261805d5172a30d228f4e97c526c889e803c8d9535ca250e7890a992260e2be8aae9290dcbd38d8df5b8c1b0a7175b37bf117049bb6a82a242d3140c1954d8ca07c80c166f279aca94bcf88511397d098bd1655bfbef63625bd0e985cedc60580c29fbc206c3628035e9d4ac20e4a50f5d585600fba1e6838b8bacacac1faea28aabaa2b83552896d514e401af33273f90407d39635ba8bd30532375e34aa80984ede2aecd8484c0ac42344ca1561df1cd2d5d0f35c67845188c9defbdf78685f96c8cb40debbaf2ef0113b3751b0c03b3b2d3ff1981806fdb33949cbbfb5895eda5183c644a23f11fed37cc8d4d467d6f6ef421201f1326646e66595f6c4c2682d04611b44302f889d5447957c882115fbf476b8284f1e5b0eaa255c52e0dc15e51a28cbd678021e4cff74c9131256948f3c88e31c61867cf4a4118b082b67d5e0f5fbdcdd0e296105a9482589213272e315609eb0c6b2daf98c0095a64cc9829d2640a062c2260583d8c3498ddb48e419b156f57dec6e4eed1bd37e90dc9db137777f7b71ddb6683bfb7a96b7f651819e44a9ad814e11531175e3f30141905c67ead56138f3285acee3628e642079916406a5610ac89af136c4669615aa2e424201827b0602a2aeb9a41c3b2b816b43f2f1f5e68ee3e65fb0927a302a3f0e506667b60d6634d8f2d6f5a4340d8152874c9205ce3d225d0b00c51d15abfd6d074344c4994b8e18bcf537dc0d76059d13484dfa1b5e259e2eefa60cfd6b65a1b8257d7032f00df92a635ebd081e4013de40d9a3599b0197c93d7e3c9007ab0f02098f6a43e04f8d9a23d6fcaccb00c716d095184189e3a9f389fbe4791cce7dd16ce0b97d4a739be1ecb10e378da9d1373a2ddd792f914f79896cfba479d497d9a680a94f6f07276226ae2a038af5febca101a0d6dc4fb36a5887b459c13ac3e3b24bc6de1cc7f637e399617b5da7db933477324b3c93b7b4844dd912d8a0077fe547cf1b1cd8ba2cdbd156d6c6c6c723765a6289e768b285f84b02c7376e76c9851511c45c03b93b02fb66fb50c61c52bfaef8719b85db4606a58c37f1bb13c72b1a7b0c0927d552e27375d165a11176757d62cb1483fb1a27184155bc2baac206182618f8c90915d23644efb668346c886c0b4f87a246d9eccd47c40de2078812e67eb52479ab9072bc8a15983385b5b124453ded63a34e579124d7bb636b74653fd249afed665599279d8f9143cc24182d7a5a369584620b749fd632902e7cbefd50d17debe851fc07dc17ad1175e7f2d43e832e7ec67cebd599b4230600e4d75761a36394aa23c40740824e7eeb973c408eedc73b9099edc8db92f5f836abd841f784f8e3a37fe8efca960eb1b9337f27478e808de6b7db34d936341fb664b0f745fe6a475e780d999821f13042f801ccc9e46734837a143a2230229ce305d13a3ee6ed2b018c7ef759ef5ddcff75a8ca2cbd1c5be1e167c5f493729b056eca48ecc22ad229b2220443aa2b717a50b1245dc92f619b1c8f9acb81851a48094bd58e028222f4a73ba40942c26db17a7a8b22fd2be174def7d7baf591197c760265b1618779d61fa90e58b8d164a9c92f438e1280b6fa7ff932f94157f1ce35c8faf302b4adad6b191099b0af6b6c52d80b6968468c59d09aab2c60e81da167b100ab7d75adb838d804a50d3724b636a4bdb61bb868e7c50f048f1df9377fa3fd9ea45190b262f6ad4d0f2b46585949de1b0e206cd542009b38931c698aac7c618638cb118550af147ae86a2ed81efbd97877dd6da5ecf1462ad45f106cd8ae2b6dea9f9164a57a45a47573a1b5366acacad4a85094040d2ae8ae2969ade9c8268008b1a1a6f64585dae809c699b379b284f6a58ab6fec7ac5d9fd08a84a46519227626565b240e01f42fc1ed5b02b255694b6bea4b88e72ec3668764403cfb0201a256f433cdea8a420c6faf819af0d73d5479bb34a18636cb4b1ad4aa61a232d4782c8e4d0ea7126678366465676fa3fb786154fe0d36fe5da6db0ec6d8c5a765f8671836050d65811045d7e9cb941b455968447e825889a3063665dbc76e0a00b8c0529e52043c497c36ee59d1284aaa010f311060b84d591c3b4b8b5f6da8bda315f300cb4d062820f3129a1b41c4c4fd7c1c636d02e192d099a51761455e4cb6a3111993c2bd54625ce0491272a9a2c8ea52c5acc32c606ae00d14aaad2e28b187b63096d296b061491a1205f41336cd6d2560fb9c1df528d9dfecf9406b9706cd901d8a0180eb01c159c49777717db5ab2ddfa90ed2c62684569695950ca406b4c2b6927b6a5b5336c506c4ba9877971b69ec2dddd784b6bd6b0c064b16145d6c46249ed9012f334212641444586beb67680707bb53daa8abbbb3b36c218630cb566f3b6fd9e9d5aea894561f12cb0506e713f720e106ccad89a891e3dd6bc28411c97dcdddd75482daa9eaaae1c07618c838e422a15f6cd06c1a8ac983783a61bb9fb0a522cbc4903b8603933e5a50b132cd62a4a0a2caa048c31c660524e1b3b58548acddb201814189dd516ac2d3574374cf0417c24a356a49c5154d510b439a415ae7684ed580b22c4c586919951122410a4b89a5899a9128589ad2a3bd264c54d6eb06c6c0533aa1b5d4d6a9cd0b29819a34242fac1b9318de7eaeeb9111bdd3c66b8f1fabdd77d198fc57951f1e69b1b1c8beb4ac176e015a7a54c095dae30b1530e8254970931dea4546d21491dd91655566e3678a4ca4c769185055658d9333e62a3481fa932db391b3c6243491cf34195b72c6a5158fcb86cd4d2129aa4256788d2a000658186bec4385323482d8c195b8345e9fbd285f1ae469a1f674ba05468a181b334ae885ca5515540ecc59030a6362a3b40e01969c4b0545c7589573aa48054ace00a83c6c4843523194e82ac513142336363ca3e591109c34171526306851335ebe4eeee9ec7aa2b398f4a6c654fbc240d915a4a03c26d8ced6b645ba6524182141950ed8ee6a3e9efbde088d190b4e780d7e23536382651ce28cad06e609f9c73fe0cf43c1332e7ccebe59c73ce193b762f02e221c4852b4794321d35c27e674eb8392e23ddddddddddddefbdeeeeee7eef757777ff9960ee78bddf94cebdf7de7befbd17dfdf8b9c73ce19ffe0acd911f6b29fcf82bbbbbbbbbbbbfbbdd7ddddddefbdeeeeee7eef75bf6565c892d7d343b93318495e655a7c213263053827604443f70c8b262d988919f1d993d235efba20e10c4d0b245f3cb228d16026e50ced2fc63f7add8c3f8e4eeebdf7de31e79c7fec8c9d4ccbc2cdbc8cc7ebe20206cd6cf3bdf7deeb3bc99032af672fd3bd1dc05da161c4a4820a1510d7c8bebe9c289f220484094bd2a1c34bac8bfd7aa122cc8de3dd2b74efbdf7ba5ba47bef75fc56dadcb533c653eebdf7e6aeefde7bf1d0bdf7deebee370b9515b95539bc8bbdcc2c09e7c88e32e7dc2b3b336281b50cc0ac8ae0b49aac8d7955b0276a408306a87293467081a68c0cb02c5f67457e5c8cd830509114a92c3ed0cc54c4a0604bdc9635bca465c84dca538b271748447e5bb26c29dbd215ee1142e0c0072068b041f511bf7efeb1625454f8397cf327fc0ee16b10fe06e17f103e08e187103e07c2ff40f8238421096198c7703c35fcfc5028dae24e7f36f63577855db378fabc885d14af14326b4c9f37356d69a0a04972e6481c11335c6570a84045e669cc129c142231524c842903c6cb972b5ea274517b2b73f3e202644b0e2d36b2ccc0d2e24a14232b5150b4c5550143254b0a284c598282991423514c60db8252c2931a4e5e34614362c29662099a35316a5b94a490a4491a1a9230b4ae331e6658bfa8b22632282c8e40091a53233626cc0dac8a91275f695e63454e20e2e3841b43a6ba9c843c5132e1c950901580a8f0a30b97151f6c3d94f020db5164eb870ead1c555a327030dd705294e5e4049699ab2f2560b1926263adea47f53515444a479415148d1a2e6834399ad1c427e3cc5318272d31a634318171f602cc8590163b98ae96a09460243159c182898a156990e08eb818512972428464484c6848500f155929a47c31502c490a4f2c110a4dac5981cc9a37356d69a0a04972e6481c11335c6570a84045e669cc12dc1a9198351361ca80f1f2e58a97285dd4decadcbcb800d992438b8d2c33b0b4b8a266345a51f3b5a1a90247c52d85b6296c28a849f94531c226040a8f27594ea69a3c31615aa2c4684d894f0d8d12b8246e696d48d8d0d4ce7e66467e42ca7890651d991a7b12630a4b620496c46704cd179c579a5b068bb435808d016a0bf829c0c807211e782420abc31487a70d4c19a4196948f32100cd01e00ce0f6d386015b01d42ef811c0c8008458c0a3822c9f290a9e04c0140024463d487c004083c29d6edf36019b046a197e3c463008d9e17121ab37a5f394c3848366c443f359407303b77333db6cd8746ae58f34a285e45c8f1147b6816b78d355b26745a279e6abe6f74c5e879a66d7b7b97eadb56ab8b57eaeb57610d19f0ee04fadf5673666d75aebff883f22070b022c92ab48e68c75ec8bbad6e724d41bb34fc98dd519b307b90d8f91a8b42a9f693ac610e04c000134007318000083301c06a224c9611489647b14800b4e82385060228c0623c2280c0606048140180c04890c0008c00010c37010846128a6f4031591189bc52993404871cdc69020bd4fbc283fee81a0ad4b3cd06a4723a0db2c8e222e8fc83128aa8d6c92fe41e22df0338c202bc872bf6c5ad1d3dbaf0be36af87483276be390a717fb608a7114ed60a07c268786fbc842133dac2924e97c83e441068db82478446068495388a3f66dc9fd44fffb504e5642d06c6356d4fdf85afe6f1bc4c789089f4d64a2cdff6951558fc904ce9e7136559c6820000a0634c1212e7347fcebd8cb3ad10f825660ba061f7f44b7840cfa5db69d3a004fe73f304a8861cb31245836383c8a0802f865f39a1dd3ec7400269c81ec80f771ab1cec92a312eb91d840635483ebe4639b459fffda33a6be085cec96684082b76ad6db8897035bdea591523e5d666f316bf2ed2e76ad87973bec5bf01162e8489e0f44cca490a306980d1c5b36d2005943a896a7aa29af743dd0f9bd4055a9ea6e5801e806f064f802393a08df511c57257c093027de78117c62a333adbb915fcbf87736fe95ef00c9b54e9799b8f5bd31d7e71e6e55790c6b29ade238746ab10b28ec346877db6c52bf10dcf6e5fa673130946487f4c9cade7cdfe9baa30343b18ce51f754b309f62010656a6079b3db8855054738732326610d604a6d4b497578c918edde382a8addb0b11643f91c41e8e2886bec1de45ba8abb5d0d87038c5996b20c30aecda4476a88bc07c43289d99c14044d8c750b4c6dd76dd0ed4cd0746e6291ac17d7306960d123305a95515302bf8d9009f9a3a885e70859078262a907671f19d839d254a30ab605f230d0640b541b692314c777631442475f3df419882c7a24ad9aaa3ef0acdc392e8e001434e685f1e3228af8bc9330e49b63434ed41439716493fcbd00842dfbb062fcc40d0b44bd33d39429e99404aaa50f05c34d53d4e46120e23f4ca6671296cfc6726fed108de0402aad901f0ca224edfffdaa7f843c420fe2a3d9aa3b9ee3b9937d3dd1d7989c2902ae5a12e237a6e2777c88633799bac25474489c11700ec9962f5822d58e4ff4045a52b40ff7ceb88f4d660849cdf98062ca7559fbe0c9e5c38ab0fc037f2db0a85e6a325420fdb8104b321880f4cb21d006bf5e69e1e1522131070c124a65d63528760cee2b274ce0e7d87267dbdf255186f32107069d9dd9a1ed718e52c1ca1a86c370a0605d2393ca19a76d6d54a1d961cc889f0670a24a7eef0134f28d3790dac9dc09c38300f9ff89c64a73023baa908b19d0bb98e699ccf63f1e16acb1662aa771d2103803e481989f4659659dd0afed6e338869223c6ee94d1b8d9d8748416561a540485d6d4945df64411a9ed7a3171ca908e4a9482a5e8420813cd94c5c0387e01489c33065a77770ec07e06f03f169c41eea6750b8996d1024e1b6c287af75170679e0bbf2403e7c92467900d32d823417822f7de9557c3391251021487c98d15f519c5f5d0258195a60e92cd03ffa4bd311540833d935326a4eb393b10aec99852961e97392ab06f61afb3a8f52d03a7e8d061682b1625c9e8b0cde76eabc5b9d14bb4595960ba961757894a2db07d0f5666bd29102d99edc1e88cf50b82917c8cb6ec375bb7bb691e151646dd22668ec52983928d17003c46a6dc09d5c63e85ed2b6ef07fc9a3d6569363ddbcecb9ecffc3a5079697ec7bb720e02aacee272d685c44f778f107641403671b8dd5fe8e7506c6aa870f194ad479d5c3ee8bbdb73412dfb6973556b0d6da168219396f3b45aab3561dab868e352d91f5456f7b599a2b5276da16a21b396f3b45aab35716d54b57159fb435acdd3668ab3f678b650b59059cbf95aadd51a9836aedab8acfde15addd3668ad61ada42d5426764795f59bdd19a9836aadab8acfd21adee6b33456b0d6da168219396f3b5ba466b6264a3ba6c4cd2feb056f7b5994a6b4f6db168a1b396f7b47aab35316d5cb47149fb43cf6afeb2b9a2b5a6b658b59049cb795aadd11a9836aada3849fb435addd3668ad69eda624916322fcbf95aadd11a9836aedab8a4fd21adee6973556b4f6db16aa1b396ef6bf586ac812f1b156d5cd6feb056f36973556b0f6db16aa19396f7b57aa335316d5cb471e9d90f5e56f7b499aab5a7b650b49049cb795aadd11ab83656b47149fb435acdd3e62ab3f65d67d73068f940cb785a6cd15a865628daa84cdbf95a8dd51e9856a4daf8acf562adee3f8badcfdaa6562cdaa8aced3dadce6a4f5c2b126d6cd27a9156f3b5b8456b1b30f1d97e5cb21b3dffacd26b6d4cbb5eed58d2feb056f7b4b9a2b587b658b49059cbfb5abdd59a716d54b43109d90f2eabfbda4cd5da86b658b4d049cb795abdd59a9836aedab8acfd20ade66933456b4d6d51210b9997e5f41796af717cfe4060c1344e31fdea874172ec70aaf68abdd446576d8eab5517b51c543b8b6a699d7629d2ba15ad0ca2a5ed699560b2b7faec2ca2ade1b4cab0f69d6a65696d6da7558ab46e442b936a69796d29d6be51ed0caaa5e5b5cb70b26eb2ec4caaa5e9b54ab0d6ad686550adb6d72ec3b5ef442b8b6a6b78ad32d2be57ad6ca2a5e5b4ca51b26ef4d94caaade5b5cb90d69d6867112dadd72ec75af71a26a34123d3221ba6cd79b5eaa396836a65522d0daf2d45cbbef9faba9f2927f3494ffabca9fa1f5cc708bd23dd79e97b3c540d813573de9a9431bac44c753a4c6a30ce1b84b86631658ff44555f1fa68755e6da144b10e090bce7447cbc7e6f0d5ec658cb7287c655935d04753222005fa5c3e42ec683aed06731b7b9b47a150f968579535dc9e4e57e91d02b79a30417ac5c91d62f3917520881c636d4966a9c28685147038478cbf331eccd374f9f78830d608a86b4c2a3f1b30ad242ead045475f59edae679cbf1da0242035749dcfbf2e89c0cb5a8aeb8eac705ff9fe217ac51ad1b5422bcea951238edd368238780992986b471e4a4f5078a86f7a798db9ce51e86c84c176e267c2d2fe40f541127e495af99d9887feb6cb2228994ddd4430a4f045ab92de9a9c921b3150fd7afb69f78a4035a1218d574ad26474c523e6eafca76ea110543065a398dd49e1f3143f3f0facb7e6a9fea819282cb61814ba6534b9ed797a90331026869a3fa5851607e255e8d151e2dd28e9cea2f4e1e63247553eb670055b65740ebd1e0c93d3da2d79d2c7914cfee6ca38315e4365f61409191ef4e6826c1bb7a62226b5e9b8bb4ce7398c8d65cecdd02c242ca43a08459457f5d20a8f9f8fdba0a198409e0707f18565499d1b2bc7083161c73dd1f0c8bffe1686e3ffb3eb67f203191f0c0beba8ac21ed3bc6d5a5814608b3eadbf5b1a470597e7f925e0467fb78effbcc25db5d433cc9ae849492b716023278fdac0406e2a553573e761de600d8fc4246941d69d09d770f52d4ef54376d963c2597fa48afa066dfcccae295757c4ada4bd85be0175f0ae45105dea4f6ac924a8b1b0d2f8a04440dd00b951b9cbe993c5f13f126c4ae5087a64791d6140f07e8f7bf01e0521f32162b0cb1346fe273e8f51a5dae62c45d2f9d68a30d5e3407aacf0bf8e3a38f0eed6fedca3d8ea1364b798b5002430bc2240d3ab6eb1b16e0d314411e91804c78d18a773e192ee384dcb333084572f381cc6394dbca6ffacd0e29446b9dfa150208f3b51748bd3fae55904f2d82dd8268d534e53fe1b693cc8b7584d1e8e37e9a4312817b4ae7ba76fda85f312bda527cb9a9838920c1615f3a503696af99b984012907a96a586b101d3ac40cadf390d71fededf33bb4f99f595bba98feaf699efa0107dd299294d731bf52a071a6cba7d76ead7a47bdb4f6fc71268c945c160e42c8beab064b5c4fdbb24f0d6cb0e8b1cd0da2016b0d5f974c92c75cdb36fddb675cc415347c0b32b59950e625d71637f31ffec6de43e00e29003dddaf0a04f7eb717bf967f31acabfa6968e4957711274a5a7fd7472ec04ffa4cd38c0c04b757f0d329db1adaabefaa7669dd18a146f3f932573e4e72e3735a01392dfabb827e3a36b90ea008b09705c977351b9af2d85b7c53fc1a569561196fc8f7da33aa345a6b2d7734ea0ba817ae527a060ffa7ea8d974f1061368a6893d1b9195f790985368400800bae48dd8b4d8d2994a0c3c527ec89787653552cf76f7b37b756b03f6f89171bcda45388216d982b8a45d2492f3734cc5bbe804edcd033080ee8a0bb99a4594c8da028d60a1d6ff88f6cef86f37e0966f2a9726e7821f991b050669cdc86b98963c7bddef45e0ab8f7205f0d94801bb99090adbfa9e033f55514263b9b7a6507f30473e23d6469ee86b4c60dffd6c57177283fdf5175dbc9e583b927ca28cb64b43bb247603343cb8ee7107240bb3e756f7d254c147d268bb64582cac9a88c4fd114306d2ce9d53a7dcaea5f5a1d7bf2b7b6eaa874158745fb5d51084f452c8f12bb2f26b343080b7a560f40e9ea9505b8f2a1f1ed3bee34109b2a86e2330eed60c783dfd2b72a3fc16385f3a30569a91a3aec71bcad6d3516c95c15beaed3e769914b8dcb9e4e704326208bd8b581032cf707c5b12599c5ee6b9e07ceb1580cd05907614e7a2f7d70d9d3441e2bffe9289dee5888d4adad1a97666ee668bb5eef900353039e1959a06e9f27c240149f139d241f08b9a014483dfd292f7f061df48a42a3343cb5b3598daad9484a27aa6ade1940d1aff99ea1684bfd1328fb2b8db0ef476fa1e79f4937a18c11e40085be1395aba3cf5eedea46258c4b2d81539d0819436acea2b211c48a0b3753d864f26d8857db3be6f9584942002a120414952860ed5884369c2b14315abb26a306f0c566187629328949a080ffa60f4bb0bee7388f1a48d7d2e8926981203644dd325671753efbf51a857ac8e8d9a9e9c19e7042a6d5f1d61d47390e011ba61e07b650efb1466a27a361b86939a75754f0cea4931c04e59399bebae17d4a89de197effdea5d745d3ce4866a6806f857d67927e5eb4aa8e1fafc2a18608ac31b9c70ac292062dbfd65755c59e6d610bddeb28acfdd5f4b561b6ccb4c855587efa6600fb9c90fd5b5e4e2a62736a09fb6c3dd01b1c59742c5d06d67ee3fb8bf853b214687b28cbd74e9347eb2f7b036e0d69f9d7d7d0a04f24069be8fdb2524a71d8ec046bd8325af5fa4304cd47e223842bd3cb0e260081aaa0afe03823a1929cf112e5255ab9801dc15a25f0539ebdb9d0b2b034e2792576a7c940282e5e811d02e623e7aa26f0d578e47d0704d05c626609d5a67dd52b62c255495f7b3176d7b5b62afac5d4be1eb18c00fb7e801feac8eaba580cc630d3acd7f768b50b91ac93201c139b54d16ac49bb11010a798a1bf42802aa6338bdf9579a9288f5764be7aed93485643cf53528ad86868d00d835399c005aab083bf60dfdd656495380f958c7a8b5fd2f02c8ae1e2757ef84285d7ae200aeba86ab1fba08a9a717a0c8b4cb4cfccae354a44d9df583e8e7c38bf2917d4086c37278d831848f391e60e045f65035fe322d1691a7bae7e2779fc3118797e9855aeff3b8c959e82e15de95d16cc699feac7bde9fb68505148f808fd76cc19a1b1ec198f4d2864ee64ef4a3c267d677f6d53b57567047d691b3c3a88c60b989fe4eddc581222dd7e713a495c3cab86ae591e60e920443a048f04a1788b36726135ed45a886dbdb3d541bf79e85be2dcfb82a655a5084b09de6c9c8d24fe3227d3e68275aed448191d77960179632a71490ba67afe641bd768568112b19553f4b41944e4fdea4d2b806dd5f6188611ba04083733addb6ad7459cc94f9bd25635c0a8397718153afab664e3d6126fa3a2aa635068b58c2008d1a26fc635bf5f397a370a2c90a83b03d2b7a57f417e1401eebff69c3143e810548b85679601edc4e1bccdd4ce83a8fda890b6839aaaf57bb511cea42f72e36bcbd6f971c1477ae002cf8abc7ea826ffa9f28ad351d49a1af51e7b7b2b2ff5b3fd2faabc08d529920dceb223c211de73d1b8922187021d7c10bd2d1c9e1006709b06c43cfcd45fe0753702521ecd160f6c496ef50c3910de46e0ac27e7e73787fd0b8463a973723e2a9e6ed0e5988623b75241cf15b7ca72c2f7571bda49c7801df0ccf14ebd942b33a43ea6b39b0a5809b20083794ea43cff5e4198fe5d21e3d6cf2c47c442dc1ea34f16617e86d86406c40b14f4f76f1b5b6290171855e59f5a0773ed2afad0be6c31809d5fc851782ec336c4b324b680b26b52cacfd7f654f1c6012a2173f4e7f40feb095480eb6d7401dd48102fdc021b3f291bf6b8190f2debe4f8b8a3491b613281e7ceeacf298340e5de8c74592a81e7045fb93e046d1bfa45b390537771f5bfc0a22dcf0dec70014636431cc99d971293a037d388913a895df9b62d9ff5397e4dc22bef021e39c499707e74a00fee16dfb0338e0ea81e3ad0b6ac8dff8dfd483b2eb0126d83c750478499cbb6ea0c98fc4d81436113af77a58c1c990a2fae487fdf649df92b00cb59802a8c7780ac182db16c644658247640e28c7fc95af3f6cd90aa22eae50a769a8385013151d642f0e92a6dc75119f13fb0f0dea8f3e091a73f289cbb0c1a52f8f080de7bbf600be8dd819039942b088087cc82914314112739ac10d018dd4393803e6682fcdacd28a685493fe09bb89ad26d4deafec4f48f26816d794fc4b7075dd47681b7290b4de878de0443a3aa11f2d3eefa22db5f2a231210d0d6bf960bdc97171330565d495653566b8f41f918b6c139ec1b11f17ace992d21282feebb8066b0886b90d9206ab0584e776f7c864dcad995e75bb410247475d1ff7def9f7b277f50a7dc210f9aeade0e8081d664a6ed0e0f191a2ff8620060c3d242cf3cc09321fe6042b436a3324f35f003152d31cc5e188bdbc38dace517ad03ff1a11336c73178b9e2f18aa4a8426de1cd367e621c221cad35f7f6c6c2a6d5fcabb3386911456415fc478fa0f611070670588ffdca5b9dfa278fa995a75cc0b4800cf23cd6f5fe6299c850124e335a17cb9631c91056ca19b6b23673cb70ea83667a488759522275e6828967d4424cbad4a0567d7ab8657b7712980ab9e1a9612517c808b4c1cc6ea470f2f27a7fc9325a5cdc7f04e82d7fab19ea68fb5b57e74760e54b8f6bd7f8b598b50c7af8c31dbd3c533bea93e5ccbf940081ad3d84d263e705d28040b04dcbc40843a662f05795031cf336f95114c8ae3fcec272b6921685a826d0879eceee675dc31faf9d07762d53ca839dde72fad1dd4352f1b93743e3a68ffffb556e2e199aa3345cb8c3f4d15f052b364d206e42825d4eab39e2b3847a550ca94689b6f244cadbe0d92661127332425dc124f9cf146f68235cbc436f1fc9191f11731bc5a578925c84f3e50b9886ed4c5ccfc1aa84ee566755ed07f21f0cb2ad91f052e098f81dbf31cae9756d9681f37a0909cc6c60368568acb9f8203c49bac2c2d6aeeb123cb8d906fa0d76d2b523f7b5ee027f725e234e3dd4b8a51a4f250dec565f0cd348d087efb05c94f55ec48e9910e601eb07086ac647e2c7f09a3c1cc481b3b56a20ce0a4be67af02831db426b93044794fe102694660abd73fad7d052e7c51c220c6e3577fd8f836d78cda29f7e81e5c7c0133f2019560241409f91c694e0a874c4ac47216722d51ac6503276e54eb322aa2b1ca2b3aab68afec584cf3df42a0a2abf3eb40886ef018c0d3596e66817e876b2554a0cbb750b2907a2f7aa6c10d4f047eaf50f24807065360dbe1d75b6ef2fcc01d7f55faa547873320f858967e0f6715962b7d3f6bf6bfab4a2b82ee4a6cafcdf6a8d661bf6adbc43971a15b8973f592c67e0129f26e992bb6dee1d122a5319abc18139c789a60bb05f0b932c1ce057ee157fbbd42cc87fb19f447a5334538cec921e843270cf4d0bd4a20c40a35aeb6ee00541507c83d87cef018c2044694714c088c080efaab43dd5a248391054ee7183e917aea7a58bc68a892d7b470efcc8088984bbceb8492e009f9a95c3780f4a2000fb9916156df390f3c6792d073637a6e53d7629b6b4fa1f4001152ea963df839c39668d39e439349b49f71044188d92f413844451efe99d70c2c561adc97ceeaa275fbc785c3a58c20acd810f510f6a5b3c2cdea2cb6c663e0c540812a380580a2ff348036b7449f6a1096d69b7a00e30c78b2722ea74229190257ab9c1c5b2b034e6e7616a7cdb9c13b160684152279f10db2ab1beb85f209576613b31f018fdfb1beb5a6489c68fefec270d57763b58a0ff4bab39a0370c29e38e794bfb3c6986ecf35daa76b8c87d426389a12ec570544ea4ab0f5197277fe1be2beb5804a2cd19db53202d9634233d5100686fb324068fb9f8d3efb436a242b1fad68dd768c08ba5a3dd57abd67c1b5985880922bcb58c990a2c54a1e6b48a6c3e0a851440b52f7ffdaabe10d40b534c8f08b6ebd846d118303aa36b31b54843c805f48fa7ac8a5f967ceb1bf990a57a8a73f4eb2c857b73fe7c55a6d6dd5106b7d19c79f7d0a35c4bca23743037cd77f0735704b122852ead2a8e2cb49dbfc6e3968f9154880ac404a9fdab28d6e399bf6d7be56b68a018f72497681946d5731f59ad4f18aa77c2e32cb8cff730b4e6ddbdf360c6e4e2b906e558f5bf895e082b496a77bee60c0fe5a0d3b404a8b8a4d77ad704c54f22c6c85fb68b60cbf36e98be2660937de3a66cdfe1fff806c8dfb6365bcbb474e9f34c30a27e198419f928582d58c31c9a4f0b9f688a46d8458b2775fb507b66fded1948722c3222583c7b82c570c0011e393ec2978a9b557f2db38303836734b1892713f8d8514be3a2ea889e555f5657fbaac8bb223fe0099fd4ba38ef369f2aa095f4cfba1eae5d4e9a68c808b49354c073c9d1fd64880588b8739138d78773eb9281c5e39757d219493dc376beb054402000538d29376a959fd38e5c16b78abec2359a9235f172d907c9f9eb1f767592f78f16f172976257e0a270d87f00efee000ce5ffae08f7c40faaefbf2e255a892e4a2e10761ded379470f4267db5d1d6596ae509b86957104cde9e422c531c071562fc888f5d08c2bca1a723e1b0d2d048e39e1e740060b1eaa2ae75d6f9d83abe386cf161ba6c907395cacfeca868ec6410b230a12935385c88b10634feaeed2ff2bc26fa1777740449b67ece170a0521ec47b61f2ad0130b082853e6bc38f83411b2c30df4f7ea6dd1d1f2466a57ba8455e9bef50093fdba4638721d487afc1e3a18b6d70f719393e0617e0fcc6a59fc31869f3d92301eef8e73104acc64e2c1d467d2e5ec1df51a953bf741582ac2599f235e01bde8d05eb445fb912b568f0f30909d44fba449b573e2682e0d5b2821810db2db5c2ff8387743cfb75a18fb30cd2b8823cf1f3c61009b6fa3900be7e683553a247119325f9412e2cbe7177087240ced3baf0ae8a2c97f71ee51c2bfee05f5895b4f25c38bf88cbc28f74a3b7117b3aae61d250e84dfc30a41fe08d40c64847610df6ac1f91c67ffb66467a0e47a4d0e41e263f6a1fe9e689e52c24c00885596fd0a284f86fa00d3194d98e152547ab3a01b049544d1f0059aec2d8f99d8ad17d547d7c12f57196412e473c753bc7b84966e929664baafe05d55327078f72ea679a294db766184efc65b5522c310b630603798b09b29d50ead1bb82eeb03102bd8f53beeb3f6254e22a400dc26a186c1d3126d1f7dc936615b85f42ef3d303b3a5a9bd85f1e58eb03f0420d296f4920bca08c1041c61de58a252eadf9ae56ba7205a25e884f7cad3906f4747d2c25735efd6f3b2c3699149a105c76527c8787b242025c6c739bdf7bf2f222aa01779970b829210ee805ae1b1a41c30f2298703c048ed6217cb0feca05fe458a6a586d42f4866fba853dff4fe53f28708ac5de6f3b8adafdeb5f4f83b5dcf263fb1332e0fe91e2e09b23374605c42d4a632a801e9d4f97d5c140b8f06d0b37ee2b85fdd507d56f0fa646c58892ebeee3a76106853cbc0ef6adf195080ee39c5eed1e1a709b1df0a03f3715c01f10761b85fd12bfeaa0fb702e5fc7bd5b360b971ac3cbba1331b0fe7569afa5c722c0832772938ecc96ab71be5b000e96d68ebaf5afeea8eda2c43582ab72d0b2490ded174c24d91398cf23ea60929ce25a49c7b712f44a5ea38cc2e443193fb6af55293d2812049f3d2681612b029d8131df9e024aff2fdab2059fc138452809acbf1d7e1a27bc01d94ca750f5968bf94b0b89de456d27510b71076f40d5f506e816c60be4b9f4c6a95ab3a85b60fe9a20bdd739083423b3c1ca1e2ec83c31694c0b81d65052e24dc066830c1cf4395115c47941ff4ec47fe5442c5d1723d1a7313dd9bc536d18f0dfb11797ad4d6bec09bc0fb7969d8393131ab7f47e15a982d91f8cccfb4760af24a06ec4a899569b03521d20d001c58406b1f475287c3c3ea63395b7eb920728534713dff2d8f2860a9e904c458f71b470fd649f6d43aebf6b0f02380e3e1dd87640b6e0cfbbacbf99aaefdb8b69b05fbf86e8cf09c2c4093a8bd4ab6070677815a1e16e193820e7118147a7e972446dd002fdb57264d8e1caabf5e6cea6dde515c1bfbbc56fb44d6101efede54f58b7c3b94bb1d6f264aef86443e855d04b1234ae066ad9a00a202766b300b5ef7308278464ea9746cab5f566a983df8f9e3ea161555157877e7d9613c6642a353365088eb92f7d496597351821cc3383f1d1929abaf9296c55db64ed5bb5cffd068cfd7eccba74ce1203d0fa2b843bb816c1dc38608c273183ff484c5b57da4f2ca0417bb785d4bf28f81000ee1178373bd2d628776aae5866fabbf523ff47824eea2054360cd67f32d62fa4626075afbeb582abb0837af8aab9fd06508aec63c7d98f2f956b3eac6a948d7419ce18b5ee537a9d5e87e112f7e4997d8eb4de9f21befde9e6acc26e7d43b9cd7f286af187d53eaf43b8f543a1b832b547cc3ec9f81a2c1c13c462204933ca3c28987edbb40a2de0594d7cb955b52a6db619e5fd6f848255c7ef72f7d38f93664014b2e451f6968f19be375ef63131235cc11ae15858b1fa9dab1deabdf381ed2e9cffaa0cf9119d6c1b313ef73e3397d6fded088fca66869b7550d4e55beb1818a53289e2c57876ac0371955db90edf7ef063bb2d47d7232f663f3202aafeb420fec31e5d32749e6d2df362fdfc171f58d769e31017a8ae33276b6bd5208d664da004f75c81add659cec40c40ca78368380f55ee6c6a99ea9aab3ade7e9bf8b0ae3a6bb8a3de4c476ddce58bfb2c49686d53b6c282e664613544b340c014b828f9c334f4307e184b84b28541099a7c33acc54a9d6fb719d82860464ac8302090f3a54dd0bb5ffc406aee1e043885946a412fb7a0c4ea1a79009e217979c5f2d361af6ea55f3f88fd50987e59a176f3679c28b3755a49d29a464ac2c467b4ef57293f511e7f17a947636b01e2e65fd2d67da7c34a6d96c6252b6312d335e132a01ec24804cb449df7736caf35d000db792fce1abd90a2479e5db6bc2bc363aeb8b79f357307f3b45c779c8e15d1fc17ffb769d8576b9396568bc7a52a3fe977495fd282c6d52257df34e1b7f0b783ef37201d1aafcfcbb2c3c9813244b0a70e045444ab1275367620dc68cf92eb2dc0f92fb2fb204355c80fcf7e94e801797454b2d9c615d0b9bc976bbdb065774a25d20d1e03ca673f14baa042bfd61925dbc95bd527cac3c05feeb0df1bc519f7b411e502f061db8f02a42489e819fcacbe2a502ecdb6019cdf4e0ba82d657efe8469e01e51bef2cc91a58ddb92453d9608dc78598e287951025d3bddd91d1fbbde51b9412c5c333bfaf40295c085b1ce41154a7b9872a11546002dc71021af9c5655b400ec29236ba3bc8dd1deec591f59f9dd958ffe5e8d6efe1527f49f4480c679fe6b0d32eb7320b0959ccbd68ca9345510830c209ba2758586c3ed00fe901396c80e2122f1b0346d119b3bdbc093f357a5257667b69657777f7921de5063406ec054e3abdefc88913214186a060891151505949d20236671541774a2cb358a494573a3dc980c38b2a8718bebca6b822050649913ca14418000560a24c218224963829aa5264c1dd5949a242902c4990177e20f34412219400c25444a38841f0eac80c34748144040b4ffcf044d12cd3a7151150221a2c29b9404396114041244261458895a42a55dd891d6c8fa198e5b1ba6ba261076c8a072b5e42c0c5113e56d0830c86dd80059030555d40f192447ce2280a1263c298a1a249151da6eacc8e203d9942c2e9eeca132fb4be602284e625812941cc387142c3102f4573054cc43029535da4955a254f98ac74f131a5882196442798ecc04488254dd03ae79c73d61499519e88524557a0f48818e5080a7f88222688a7bb2b51a8f49aeeae4481a2a79c2224ca48192f3f7cf4785241152e70081282a80ff4008238e6014a681d526bad5452f9bc74e05ec9de277797c50b90be7d90ed024b9165418498ea72775b7490d2218c9675524a29a575560c0996d74305294b8d50fa812b9628010b82482102178a681349483c50d39d952353291c792209a51c947cc0c0848ed2cd39b758a9e20a0b3064f6ce30644c141e9e76700a93252e81040a8954cd2af0e024a32a50ca01921100c17ece4881d28225292a7891c276f83085430d3c540175c57d52475ad06777569038cd1f5a5657690f9d6661c4d3930d220b1bb2b09366d788677d5cb2ced094a7d63ad2029d534af9a2b4d65a8f48f9030bdaedee8ad212768b7c55b6a0638a2521b6acc082284d8aaa504aab9118514d6c00024818293bfc90c1c1480e3444a1421044b0a8c2c4a5804c0d570b99186288d8162b4b58990a9ad5894edfacb2cab9454ad24a6ba572ca39a7b4d8fb68f15562baa5e9792d93599da453b394524a794beb16a5748826193aa574b6b4219a90baed6e082c5df44d3f54b624ab10d2824aa68b256c0d98125037e79c73522194524ae99456461685093aee4e88289c2811311ca9d46841830328a52d58e4471499570c4784d96286146c2c68a594da59644e10b6b0c24b96312c4851a4688ae9b3d24a69a595525a69a54fb36ac173d65a6bad94525a79d0526badcae426664869a43e58cfd522b5d65aeb9c524a396badb55649a594524a292b96524a29e50f5a9eb0bb2ada232c1eadac721f122cabb56a0b3e80608207114c5a604154424a8f247246a165dcf28794524af959a491c6f8288f2d6ca8d6e40bf34929650d36526bd2499c3db022e5d4e74929a59432ba54f052042ad1a55661ca876e694d4a29df878b0a57e488c976385343961640e9f204c5062a8484b998e22251484b80600119269814cd24faec32439f5bb8e893529a99a0544a2969dc3205a5524a49ab9472522d78524a29a5744a5a29a594524a694b4a29a59454de4c4a29a594524a29adb2564a29a5544a29a594945629a594b25629a59452564aa594524a59258b3e4aa594924e4ae99c73ce3929a554e289c9596badb54a29a59492bef0237601d265775ab48ce9db07591f1bea471e6aad9652213c3c00ea052db2b8a28a8b164a8020c1458da51794f002660426d0010534524ae79029e36b6a09314e985942040c51355bf00085892096708108991c8e80828282828282828282828282828282828282822aa2c813921d9c8828c205940f971e3a74215f2d2667b4d5c89c3f68fae10b473fae0803448a132a78a06284db92830f5c9c8122cbd297f89404043237581933022044b08222c0d868ad2f30be9c0088129209c03cb132c597209c10e0b40216266292fcf0256b2d2f2c2f73032ebcf0c4892a284b515e822c90923a25a594563975757529abac52ca9a5d2594124129d5e42c3267175a2ba594d25a2945d2a1da3cadd5030c2c9fe0852710942962072b5d7a604148d08c1feccd5244766b554229e5d2a996a64e6595b5425a655dd93967ad73ce39e79c734a4929a594525aa5a494524aa99cb4ce39e79c73d6eaf3ae4929ad756aad39a7cfbb6c7c4c4a29a594d2aac9227366b982d63a29a5b34cd45a94a620434a29a5945230f969ad5527102c89d59c64e48915568a682149aa4811dd92454c1615c839e53442a9f4019241472a1d1c5245920e2cc9628a215065a29615aa9088324af9566832c6033cb40ca9a10442b2f4c9d4a78c2e6a097940422216712950b202284b7e6ce104a5894b9c485495d21e74775c8420cd702b7dd032a99406aab59cbc196b0f28526a2d197bd8f0e29c73ce29a59c73ce39a59473ce39a79432f6b8e1c1186394524a19638c51ca113c577b90e021f980218a182f3f347982c50a21533e5c8450e9b63b2e4288e8db07d5202ae80a58aa3a755ab0a8004bd4173a8178f121231030429248822208102dfaed9b7ed9e3068722968841062a905812aff4f8c22588999e75c7058948109518972d1dd0a13e5c4ea0735c76d65a6ba572ca49238ed3d18794442cb9ad561fe3338b836ad5bad5facf9fd97deffd5a5dad5c83f3b15cb98e8decebd7c8be426d67cce46ec568dd19af7dba17a03fab0cc0ba7efc96e7fff9b7f6b5d5b3567f3f9b38effb75dfdcb879fc70e35ab56eb5accbdacf2afcbbb323ece2d7af11bffe51cf207ef55b5fa3f2d8c28fd17798ccb06c7e1ca1dfa7bbe2fa5bc5e4acf52fb0fae14d8ea09f8f5904fd96e3d09f711cda5bcc730475cde373e97cd6dee663ec2df6170ff38d7f0be3ed8b173c04d6b37ef5446ff5fb6e2cabd8e6d5dfb79cc537146ab611c2e51b8cd701fbea5d363aea2b8ef3301e661bafe3bc957a4238aebf7ff9a60376fb30b88db2db4a91d1f6371b55c3722be5da19966ddc8edfee11fa91b6a231b6613f6f17b81e6f1cae1bffd6f5996be3c09ff3bb3ecb60cdde65d0efdb0c5c2e1f9fefd7c6e8b6d5b2f7beb55aeeb8697e666fc3b7fa3623f4ba730475970dd78d7fd767d786cf001f3921c6737b1cb72b03fc9bcb85f1ceefdaaee7b77b1ba11ff5983f887c83e77a311b49091ffb1a50becbf383e06f412dbee9fe70cfdd41dc08c038fcad03ca37c7646b54b7d8ee0d83cf2276bd4ce38801ce3ef6352c578091cd1fb8deb25cc7c6fcf847fd654b44f7a6bbc59fd5b9a520f707cff51edb203cd77bea838ebfb926ed80ec7fc6b70a2b5572599bdc5dae2782aefd8fc1de52a0ea367f818d8256ea8763dae75d36f279a2f7b363973edc09cd4b1a9e42d0ffcb3660f4774c34ff6615ff8df2e8f98d2225e5acb6f49e1df98e510fe87dcd8e4e0fe83dcd8e4d0fe83dfd214ec1a1880481dee38f4c2f053a88dee2527fd9c6a958264a7942912a4e3d219d111af05c5d38616e2fa74d2ea74af4c9e3e03da54f38a0f75420452ca40a11e9d5a3d2d477baa4b4b5a812bdb7e67885298b29fd510c6bb654e989125d7a429b8db2514fe8add21382ef63d313da790c820f448f2a41243864a32491fe7effe6d9350abf633ac1946e7530bfaf3b218098d2dfcb579337e4ac5099c1224a2995c4aafee48ffe1edb0d820f543280804a628c4d5830cd89614afabdf7ca7ef5bff8faee33bdeb733d97d69acd63d66518d75aa5e77ab6c973393883ae80a3ea38f2cfcfacffaae5d0bac50f73988d6236b2368716cd3cd76bd2b4b79a34d65b9f3d2c9bb4ecadcf20964d3af6d6ed32d7b81dc6db273ab7041db2eb7c8ccf74768c6d95745ee7895e4c7a8e2a87a3ea303ee7b39cadbdcdd67844da3109c61379aef7309ee8412525d00c73f8824a8f83f7973b2af8822f25aa841dc0f5f799c4b2494f138cecade13afc7b7fb3bff2a23f021d3eb63b06b74a3a64d7e1f649b661575ef4779cb7619eeb056bd51abee0902baa1abe4a803e682bc5ad8dea96ebc0771dffd5e1b4fd87f46ce4253cd7fb205fa481c701559103f08680b3590996f23855e609d57f9647eb7ace8edd66c7aefd705212679b10fb46954cc0f65bbdcd8e7db33c87a3eaf9579f59253844adcb32fa845e79e7bd9c2a81d1f137aad41f6df25cef2395f7c2b969601ce314047a8fb3c72056d443c530e338f5ec4b6eedc738f53a76336cf6d555e9f6b3e8c425363dd77b79456fb1a9bf88048762512cb3dd73f138f55cefaf0f7aa34af63d842fa5d4f20455b4d9dd4711ea9050f3345fc375eedf5029da7143a5a8e669ec53000ebd22fbd8eb09bd6ef996032669aeabe8bb23f05ccf49550595e99be4d15f9c7a493700b9e7c29fb910b463b242a9bbba63aa22aa335991d49d9622a6decfe88e898a1e7a9c721e3ce18682a8bc448025061cc09829a2dd3d57868db91f5f175de703d7f3afbce89adf315131a51f75bbb7bae18e33fa35bbfb0876ca89e0dc923bec2ac914ded12a85778427f6a3479d31465be50740d00120358c0c1f70020899841218b450a1484424475cc04173c185237186224956200940d39204a54c8c19354022493e8a64a06931a20520d6c082911772d03e33002952450c3d8a1c917942d0c50e524644924591265531340fb4a0c810aaaa135f66ac5881cdd164a0a285272470221329488025de683240d14207a00d9229225b48160c4d107122ebd8440c11216aa614456489971b8d20d20292076648550e95d298c469081332701932040c419621344c25430c1112540fc00466a409a94815a5e8932a9c1046a86ca1414c172e5354d18496b4ba39830c8283541143bed8a0048b26a8489224490c3549913e69a5d8474d128fabee133db963acca1a606c84f3c69f411e3d7f766fbef9e69b6fbe55aae74761697b6136e9a4a3674139db3970bf9f6177b334be8dd0318b631b3a3dd78bbdb51d9c0fa9c4577cc5577ce9cfe48654365c9253e2abd62a1a84be4f63f372bb9bcf30976f387cd96c98c4a4f36fd9cb8d23739dfbf937ac4b4e03ebaee78a552e8d5575b7fc27c8d7366beba772636b7e9c349866fea4a189980683b12b10d4efc5fcca2a2b10d433c761e5de826ad5bad5fa67228240ef154081d0bfc5aa78e609e167fd0b7df3656d23bc7dcfff626f2ddd33df70e73982ba24a1e6e7671bee37cbb21d3d33719d064c1b041225968a76ccc7087065fa3d2a2282799fe9f9336c6249fd5a20a863fa77d3b79b7eddf0889339797d40187cc14da5930276946147d16251556a344d74c5283ffea659bfb5567c23fa408b9acd0cc0f4c3afa11f3e5a2b764e2340167fc1b7f84470ff733d983d7cf6ddab350ff943beb95c199661fd1a906bcff5b06c2419e0ba835cc7c67df835eec33fead0eae772ef9cb3bb55778cff7f2ea70f7a2e47f42cac40bcf75e851fffc1240893aadc27e43e4e611653c29a584c8ac5a6746badc5ddde7777d77b637418120c9a661d39b2069eeb61317848e9ef9d449a4bf85a1b857581b6a5bf055fb029676e1d3b30248c08862fd985c6e0eb09652f7f6c3ff46c54d5e2d498327c7366ba99a01ca7e4b79e34974d56a94db494fee494fef8e69e9ef8b6c1069bd6b17e586c0bed63e768f2c3a023f8d5aab5a5416030677f770e8a64b11a35164df9e6cee8261db9134cc71b02faf7253c21a42774f3ef251de9ef77bca157958d307ce3d273bd38a502411dc7cde387af9aebad4050bf1c877d2c1b65bc6ffee6edbe7997f5dbbff9ec39314c679e5c1ece01ad9e9e7f3d211cf2e93f9a632be1684ab74fd52985d0c2277a525e7ba185f099e9f0b71ccf4cbcf36dbcf969ae78b6b6ebd98e1d07e781f68f9aa7a9d941bee8061cf25b4f23378efaad773b36ec7338a7de7a0c1c3d3cad843867a545cbcf8f3d966be4af75c79ff9b1a7d1fafcf2e62b5b313e11c4dee5e8b2b85db74acff570ecd9ae2873fdbe95b252362afefdac629a6b7e6a95627cfd7bdee1bd6535bbf7ebcd7ebec013bfc419d7b9712f86f37ea99c5f8f7deed833f74437e9d6639fb1b5d8565c2db6f18960bedbf5eda85ff99866f3ccb251586e8222a9d7c7590b94999efd76d4318e8d06435ea37efebb71deec9f8075fcd97ceb68367f2bf5a49e147a4e126a9ef3e75b8e9b43c0bc7e866f86416f56c9861942e398c0fcefaecfcff8eac58bbcfabc579f753c0bb308d9e77f5984ec21cf385b7d8dd6c3bfdb2a156119be15413e7e984590f08bbebfc3febdb73ed163edd8ed763dcb627fb1331bf56796652e7b1af9f18e6ee19c585f6d1d4f84fa2cd6e76cc4a281df3d57b40f33e6b3b5b7cc2bb74fb0e8cd26d570147a9e3fce765dc6bbf35b2988e1b65136cc73d92821b4ac61c3dc7c1fdfc76acd463573d908efcbb767a6e3cf18cb34ec577b01d8da4e6a3edb1beed934ef3209fc69b84e037a7a780af5690b0d4b45351ce98b805020f2ccf490e399d9913975fb34dbd2709d06d07ccdd7589aa711a186e916f6cbcd74cb3714886c273d8f778e67a6d3e75b87048e42cd731e9920d07b5744b35d914d82433ddcf248d2a275866118da65a3112cd1b353fa7b202afdfd0d537f0fc356e9efb575eaef2d0f38649f5cd1f787942348af2724b4c1d756abfafbad9ee9efdf1699faa37a425b9cea669ed0169ff4f732fed92408247589f47793fae6facd8ee9ef37cdd259e6345ecf36ea223d21f762c98e09d37f44a7edf2e8ef6d9827e48618624c7f56aabfaa3c04d30b7dbb44ec9435d3df677cf18fb7540222ba8d7a42f906c645b71c6bd2497008229d7942b5a9563da1caa5cbc69f6164b46bd2224c7fea4b744a7f34f07ffeaf3a30d0f3efb92da0ddb3f9aed9ee01d1d86af3eeb92c666dde65afade8cbb723a5bed97c8ea0fe8f65a3eda8ffff3c968d7c60d49a8df6d76cb4adb556c6e39d972161d0363cefb2118fcdd8dafcdd3982ecd342db27821736e90f2ac1a2c5ebda10b06ce4b2d91559bf7aa13f27f7de8b41bef9e2bf187e0cb6eb594eb6b72bf418dccfd9aec78c3fefd7e4b932be612d58df12eb2f7f4ff6537a2e309af5db537a4d5e857cd3da12c68ad1018ff144efde378007ff448fc53fc6bd9cf5bfe17bb0e31b606b1f63ef3cdf38dfc1bef1f98fdb83d7b6017036ff9bdd8116a334ed595063693b37383b2ca70b9e7e5c183cd163395de0e21b07facfbfc7604737e302e87401df76f49f1f0e9f9ecbc97c1c1c1c9c9d9dbfb9c1f91d9c9d0d3ab16e1e3ae13cdde0fc7c16250b07e7a113ced3ce0f8be584f3b4f3c3bab96139fdf0f72c9c1dd6dfb0587fa3699aa63dc7a1fd8ef6381c3aed70f8a4694ddb389ac6fa9dcf58acc7da61b158dc042db276589ad3136b47d3de69e7bde6f48430cb8775ef947b87fe31ebb5214ed472b2794e93cbd8f9fb8e75773ec817dda0bdd3f79ddb5a3220dfe2eff0f88a3b2af1a8a44406dfea0ddf340edf5afdca6c7423177a8b2f25cd81de401740c3a4173a68eb4083df8266649003f05b0b00bfe9adf62508f47ee50481dea6bbeb63d58fee393939adbe65ecdaf7bbb77bde3ddd7b9e122d44f5a3df27d2ef73c0b77aa4dfdf806f5a49bf5f003ea6df2fd3ef13806fd54cbf3f00bee9fb413ce9a9dfd7806f4102e05b075cfafd197c7355e9f733e0dbdfbfcf92723f007c6bdd0700df74bf0fc4b7daa1d3987eff4cbfefe25beb3e064efd02bed5a82aff73dfc7dd6fd9f0ad6ed0efcbe09b4640bf7f135f78e7beee3321fae4eccd55d9b01cabde8f9e418c02919e3dd1bbac8bafbcaffbaa4c1b78f50cbbce39c7f3748ccebf39a60dbc7a8efd2e2cb7447233e48fbd37acef4f525aedc89f7372c638e39cbd7a9771ce594a29258b6f1826595ceefc4ee6ccda397c3bcaf96736ca19de3d7cc37acf677b9593b35ae5fcea69365ae5609cf9a6434eec003df3175ac3fac434c8a8f243cba9200fdaa003da45e77ccf674ec733f8e16ca4f3353adb39a0fc357b63d6e7277af165395ff14d6b9c0fdd4b2479667d96f2895eb673bec7ddbd4921f966d67b89e43c78393fb103b89ef32f1be5502ebaf5b9f5f7a394cd5619ceaab2d6c7a8d66f312a0cd1bb3b56bd7dfd37fb95d6c37a1a58d770e0cf5cbe8051ced3c0fa0bba45b35e7bbcb3c78ff909b0b3def5157cb1e1e7ecf87bdbd7367fd6e6f99ebd13c3eefd7c6bcfb359bfb37b2cdce06abf8ee99754920299245284d6e9096afe2f5fc088e769609d7f266dffc900069f616e3e9a0b7e30e01b072ed8d1cdf8f9d976749f7fef76b693f93c3c3c5cc7ec3c9f41ec347f988d9ccccfb02c02ff9d7fd96887e7390f8f469cc7aa29fd52d8d9989bc1a3054bd3cb3e9f45b97acc69c0f370896747e7ff7c3e9319e5a13e4f573bbfc32f00fbea7df876d4f9bf5f6de766f07ccc46fce3d6b9b1fa9d8faf03ae7e879f007be43a66b79f4d4cb391fddfecc36eedf3e0b0cfb568fb3c1c2e71bedaa2edbb0e7f85fdb3ab3f01f6d5f3cf56abc7e0733330b6fa973f883c78f41537c13eecf831a701feb8e3651bb0f313ded213dae4c681befac72dfc0bc0cec337ac73fe6660bce25129c68e4a9eebe12cbe308755d986548e89c886cbe07fc3b7d7383cfbddaa11d4b3a818e6692c9c1fe31cf30dde902b7a9f6530d32c3a7facc2194bbdb78cd3ab802c566559d5992772ca1b725e96e48fa7fede1da97a2949c9f2852f68e65dc7f422a258f4165f4a4f08467c058dd073ad5ab75a34089dfd16b351a62f370c1830ee1bdd0b210c1bfc2433992d3dd71448c5691c48456aacacd56394b63ae7b3ecb95ef693e7af158c432a9be88306d0dca039085132fec98892f1ac1825e3318feaaf468cdfbc8787fcf18472feb956bffa77f657bff716fbfeecdecfdc54c7af2e3f678b5599decedd7f614450977edfca27a0c58176433f0ee856c1a1f88240afd6d53ba86dd89fb6b11e5fb5c248a35fa311bbe6d1cdb82c56cfe3fb32cb6c4e4f0ebfbff32e87b09f676f9c7fb1b70e7ae6bfb7da577c078756d1dae3e47c2673fe7ecdbfd77ef599b6258f58a5fd16abe2194de76b6abe661e1541d6cb6cd4daf18ca63d0e8f55cff51e9e9b8ea7b37548a84181e66bde156577e7fcdd3734ecde8dfcf25fbe01bfe817d95e5d67b4ba5ce746cedfcff9aa78467bb9e399e77a9946963c9e9076b39754a8644c5a6972102a642308004000b3160000200c08868462b13ccd411852cb0714800e6790506a60300d87c2c11485402004410c03180600000840c4288418738c4a00027d25c41ef83f043f0fe86d125611cfae1647565c6de2258c691c0f6885ee86c311c2eb1c2e1c2383d6611f21cc7b6e33a0faf143b0edc723cd0562a39dda3f3eb2f916ed9d54d118efb2ba528c30a7a7c2c1b0f6413e33732cc0d2170af21f655117111b7c2d2c91293dabdadd4e2cd87f6d223a5a16584cc1ab5c0418cacaaca8caaec87a70f43fbe8b9ed4c22ad6d824f007412cf3d2057c458e9c892367a7851511963debcc283f4825fb148d179089f6e70027870ef11e0bab09836ee81d2facbfbf63272f1f762e556d67ee897a88dd95314ca09a091dbe66ed24ac2319823a1c2ecd04381b9e7f612d13d003eb53187252713ad2c0952165b4590aebc1ce4dcccefd56f85630dec105f4525814f427feddf577b6b85fd73790fbc2bafdfe3eb95e44b34a1555bf17d63faea10c0192109d764ce859af4999bc41eda293864d8d598a55407a61355542db5fc05089341754a1c2c29fa989d1fdfdb50eaf8f2f76b5264184bfa98ac2a2d6d6cc441ee256c30470ff3da5aa82b7617249c3d871154ac0efd071ed06bbffb6a970bc1f476e1553765a333b145efd309fe31735a631bcb95cefc4037b46f78caa41161cbe53997736084739df81411f975826258b83156fda28062410cd9978384d46738b66f4992a036d0d76a3e28c099f7aa82891615cd871e660cd0eea38d2f3d89117bdcd3947494c865551bf3458a3375e30a423579657077f0d7c7ea92e407c9601d1d2d567d481d09f69d9a8f68dcd5fd8e76082741a84100df20f17f5b07798f11348abdf9dc1806cf1a5bec2fe219393a792d179b4e4118e7dc40b8832a33b8d90da050f15c23f09a87c46526d9d533e8603ca02a7d2af7b77b1400e9586f666bbe66daf04ca3dd1fa6683c1c09db8e1e45796a198ed4acb9f75862b725126cac0effd649c13035a7de25430ad05663abcc5165e61ed1566f87ac07151d2c7419a014860ba70279070fb97e2bc817548aaefd1f809161ae14a061a11884456b1aa84d8a6bf4ba7a435a857c01406dd1484893a470a9a07f6ce6879a2729814aa31b1ddd64b3af84f9049f6ddf9d3c08cc3dd8129cc2f3b5395ba26d7cbb03168c7fe5de8315c2df414ca66008e941a4bb366e0f14f273a236a3ad1bff31ad811de32ced1604b317d8416dcb2992ea1894b4e5a880816497d62e0a9b4b521a74665b11b770e29dff0c3574bca84335dad6e6b6f9bb5abf916900b258ece0f5d53844ef5c9ba1bad3bcac8053b08c253bb8f8666c34739f70d7bc29eb2a3c62ad52959c3df0c70735a7a3e15d0717850148b5724e424c6023dc9bfeab788773e5ccf1f37adc215047ddfccbfe6262e0a6ed980eff707e4ac476467398ba6b89cccb901838830f0b062993855388f78e7b6dd0f5c6a4eef40d0817695e74089a709366d34409fdb495019860931531dd5dee01c8096421e046a938f2ab5c091cab2cc7d622bb09d19f1f298e5091e448051e3c3e646a087c4cb27bab081b3f08996c890ec73fbfefbf5a0202371a2b04a1e74215442e91838caadc952c715f58407a27f39daaaaa0737c0eb45f7fa0c50eef001d594440861fa9ba1fbec2cc87d2cf2e423c9cf7c8db1ee19608caf7140ba9dd41839af4ca15f079bba7e97e23b7181602e08b5b7df53a09ddee0a22fa563a98d3d4df4bd708f0dee37f4604197a03efd51cf116d75dfc63722ac139abfba2f871cac80a3dee172c3fd41e116260abfbd3bc276e15eede90837f004d49b0c22d4e7f9ce15bac8c9a9449a848068e0625e0a90e485c4a0049b28f1fd32552dba7afeb4938f1888775f5400830c69d1ad20db77f405594118c4205c2bc2e8865752ab2d2d76da48600940155a83145b8cca0d0ae898de8af4c47d898a1eee872f7208a49234960c137c027230e0b130195ad6e5d446bff5445db26550ca4274b7f4168c8ae7c7335c803583b901b6ee36e63d3a57870e3642dd0da47753ff19abb00b0f8e557f508932dc2d07450d94de76202b78d77d5ec4489c4a6afa6f025dc275462bb539412cbe824d03abce88c09170ade9e1a62cd71220f374b2e17fd14c9fef30cab8469a3729c0bc493f58e799b628b43c7b20574f8740aefa19da6045469637bf1ccb2014a2401669bf3ccd0f87eba261f3575ebb30f7aa90170a727885a7005439cbe1892e21c9129628e9ff0a991907e8ab720077261a8df4a94db165bcbe8b87e3bd6b7ae81d511532f2f4b21ca4dd75184850565f88f56e1e22562baba3855cd487b27383cc8f4da5247c3e91eb8f044108d225e7852945b6f18b1908eda8160c229bb86e87a0d1e3654c03255b2e5e2256a12cca02840dcdcc3a4267dbaef141c2c3b1c794644e60ed5ec8a59f3fcadcfefe72e6abb708a927b52300925d9ac45466e4ca3fb441ec67e5e0a2c28c806101d7a413442cefaf1a8eb6019dc4efe956a6c74af6214b59b37a5470620fae2cc6603a38aaa98be47d5574428a0c132c4561b931fe29b493664f3983f99b4803492a3494ad29fa425ada89a4656a846625d558acfca7191385c7c45fd8ce6ea470c96f5aa757d09c120de10abacca881026599678ba71b91d2269413d5c985c58676beadf447b8bff6f536babf140291c01e1514a2140b9c0b8d1196e0727eb3e88096bd7a4b9bb17bc3be356c0cbdaad5b2d2a69185a2488c9a833f1c069c8338e94c1006c4a7d6c92d0e20c7fc0c9bdf8ddae2f5d077c59de6ed87e13124c30706ee7a1883867a167c24a85c8f51655dfbac7dd3f9eddc27a559e5645f77859b85a0c830c0693af3148c9c384aed33fe78160c05ee04a461929902826ba4ec832218cc1e57cab44ceb50dee33230c3f763ea7d81e7088ff8f31cdabfa02a7162535330ccfacb261f32480689e5a6b6634d57839b6ad4f0cb4a6d2d40664c7236576c2fa1fe625506113296e2eca3ec5454e5f6139fdb05bd0f0b93d42749b979474fb71dc449cce15d3bd113561ec83371e4739a183d85c07491d4e21e2edc66850ccf3eccca95ba943e5434eeb10f544bcdc73fb12f582be615962dbc7214bd103cb779e3e2f918959f9f8e507ab5e4dd20f38a07008047bd0fc5e03e8f024a7ad25bd57216d9f4288460cd2c245b9ac8b08f0b2043b515beba0d0ea312b76bc7013a6a54f532a7c0ebe76cded3f53252d792c1973b1ede4a3ca69034b4ef6eabb6fbe4f1208928f7cbea53d6340fecef5889bd3cf693d560a02516146c193dc21900b2689c44f7e8b36105ffee31bd65c49c80c693451557a35d69fd2caa23c763101d3dd393eca035e73acbe0a410b112cabc5dfd753f48badc0d31b322ef1bcd9bd98011a82a23422428a9d3cafa734321586a88ced050cea588fc6237dbf869d5547797af5bb6fadccb2b36ab4a4d41bf08cd55aa5087216c4f316ae9da8ce3ca1c14586766d9ec23326821fbd6bf5fdb9d09ac29b86a13b4b7ef6038f3f5d14130fb636728bb7127d0f56ca4f06e97f795642ee48d31f32c81d77f6c8ab09e1dea01c91363868c7899252c096d9b5d6f6783d70b392c207ac082026a3f7f2873c1def61d240b143e45750fd146b6a083f12a03a2642036e3f8e52ad58e6d385676d85d13983d4978f2fcdcf3e1e6a62396b31fd060eeb42ddb58486da6d2e1b1f88ea0ce4cb1859614c248c09a602e8e1977a460b94d1c76daaec64ff70290c6dcc41401bdf4b46a31d1199e57f0ae5dd46f2e9d4d607744090b67fe43d2bef6803b03f5a2e83adfcbd138d5d2a02f1036a4cc8f5bb40674ff839c5ae18abb0bdf2db1bdd6c377354c9b58f2626c086d4b5f0b418c6b345a4db113b9dda9dc7a00b317caa995d9f6da892658b1d4fec1539bd9d3f3356edf5f6fd0c0920cb5f21f3b5fe700f09488b3c00e8ce05b436460f26edb880d931f03993f1e30c72f4b07151856a8571881b4109c6777585dce6006ae5958657fdb72cb36606acbbdce4eabea4eea2a24bb7c985e94d555a9e6f54e2639237fd691c83c46521c6e545330055e21c824a69ed12cb08043e3f095730f3a7d4e5294ed2b6395eedac57220a41e106082818a2e7226b6efd65c140735007285a9c728a1ee06511054591a0b5cbb1ee1068f280afa485197b95c1d0bc2d3290d9bc9992b47ee8a4e51ae41944f5ee2778d27e112229250a7be5c1f47773d68744408030e6e82509a5f0b19bcd34eb3e0bc0a4811d27c93e80f96f2617461a7ed160533be2954bff976c0719c8f04d418a94e65a3ea0253837fe1b0a595220bee79d6c4267d6ff7e4dcc8d127595e64b915a9d4b75d9ffea2592057e58d7e67c07fd5b5fb7a2cd6557ed3a8a31b2a04750150cb8cdec1a705d27036a3aef83ea3c3686d6222c70d8698ebc1308eb3915b7cece73e86839db1d8aaeb1ce3eafaa31dcef84fbd999459e52e88f9565cf35a10b51c93614f3ea838537d4c87e389fa8f739a4b22a681c55268cb4cc61c3902e8573353e8bdac80c0d61ef11075308ca7d28531d1f5fa1537fb32040f798de2cdd3f0e2e3be031058414eb8ffe53f686920099f6b09ea78419418e252941c2d22d1af919444abba3e62605144600abd72784a36d82c79060859ad22703cf279dd706d5eeb1f5c410616420ec8476f38246564bab55fab8c64f8d46819bace5c07f7571121c2ac375286186c0ae3bd70d3759a9d6f654490049f2775b83cfd6f333f940e3f507f03c056dabf82d74fcfd714c44861255dd38bda9ed014313e66c5de3d93191732b0d20cbd25616d1a292e24d94f92334479f36071367633118f9f63af25ba18f157c91e28faf4bf98a2c669a8a789e89f24a49e45471e5a61f83d62b8f57a7edfa88b5a1d37f9a38b8be8b6e0b3d882ffe40e1760c049b12f7568de649c624d3ecce9a4d7103cc90badbcb42d900482cfa4f44c2ca32c73f667a1d767793ca1193e77785270aff4e93080ededc614ae8543f25968ce0b742d9384ae39361d940e28551b995127c378d89e0346bee24ef5ccf840d74b00ad04ed78b54998984ddaec188c852ec723dd5ce145fd85d28b1ddd93a62d70e18ced938108c0276193f5a2011e07ebc4c1da4aac88b705e026a11743f5762cb57d0e7d18ff3a2dd63e76f17375396ec1f6e8d1df5c87f581f34848edde5e299cd9aa04478ed4de77f1632b444742f358255bb398cc920f590db11550ac41059574e2f80a53069a311102679a6f3e1c718e01174e85aef3fb2a2013d819cbe6b67d2fdaeb4c90dc8cce88cdf473e6d972d38e246a64d367b4193db094f067fc7585ebd21174c8a5a4d42724e2a25be6d31feafc7152324fbf9c00dd35a18d6ef2009df7fc0c3a512574a4c10b0c3aadffdeed12fedd866c3b3eaab5b3941b31b52a48b564b94faeef18791923de8bdde118308eb4d217d5f92156d2f9f95a5558b0982dc17362a92f873edb9b368c58735e76aa0e81f2c8fce5ca2bdf248b834228965daf1991399a22d9653e826b530599159c71357dd7996dc6f4e2c72a9bc8e284242f3436789bda75d3ebb15d896661efe5383ffccada266177ea71247ba898fa0222e29a467b737b7191804145a81860c7d737fa3d80de8c0d58e279f1b5743a740c84be22cd4bb2835271d9817f9cf8e67a7ca69f00698ce27b28d384df425acce3eb4b79530788123669a47ab74eb3470e91826155b6d2530478543668a0bd06f7084f9c54957f8f8d1673ecfe8d76a83cfcf957b8d21af74ad84d226902cce1e6293e76d41b11715b35096e264ca56a8cca159971df1701d7e84f4dc1e49d3c9e37dfe24bbcc1b92e9622500a916575b9b1227c32702a00553a0d97b43a249ad48c99c7361d5c60a74be45a3ee628987ac81af07a28ceaf3e7b94519cf97ad7b0ef9f5047aac200cbe1f02b89e4ec3efe969058ca6702bc0d599570732bfcc8da4c06ea098f5ab6a023230abcde0d27718e541cbd3d49595cdfe8015d8b4c0ccc82b2a0f2caeb9d2883cfcd072bab35a446c3bdcf83704a4e03d0022a74ee2130bbfdc4739493e7e194ab400aacabc527f3ad4aceaf81f41d6b8eaadf7056b9423a3250d0056adf4f6039aabee1a079cb374f6b6f1de12f51bd6e4f39a9b01decd9d4a634a9b676d61e72acd24ec46284e50318eebc2eeabf24bed0bee18dad15fdb3756cb886447734630f608fe2eabffbdc4ff706cd1b1a40129496dd4dbfda1e6de8c7fdfaca0809eed0e9567d75c076c94046f2de10d7a312678b04e43494b928333dddce42c073c850cd1f465e2cbd6a2056926e33928a0c5b02ad0dbda452bb49995f28737e0598d26417035c9e99c93fec4b2aebb2a0052062efd9112e4bc8978aea9fda9fdc058ac7d19fb4de9631010c9a97802c1da3fe3b87dba6fcffb99d0375cc7c7463da01fc55e1bda1a39702121d6419794318b9f98998a544ae8e85a27e60c86121225d4e4e35d279f69ac1634bfb43a83fa2591e32432c812e261d1c6eced5370a171844bab5f0206b470beb089222d94560232c5d37c24d38b09874a488187e06dbbda5ff3879c2272dbada688b522c83ba47ea9990fb2327364ac18b763a575a58d5275301d890d71640cad0dc0c4f4c405294ab0aa81f3a766fab2f50447a0bed5c328761919e3d249144f3474a12cd69c926e3b7c4c65b0d30d1a547068ed18edc996696c3b09156e5ed716d6e2a530ada0515ed9bd182b19871890eee21983a55b7d3de96fff4569b2592663e23c3affa7ec3fe9089e84c2a1c891df9bf3803e3d4758c1b0d12bcfb936087c76dfb5c8875b8436c9c733e4daec5649358506e9e8d8769f0252ef1d348a6e040a743d53fa3d8d381304302b5daf3ecd0d17adbab13ea1718bb04fe833baddb1f8ba039b6b56c8863c3d1dd88849dedf86c501348b2b964dbd1a4ffac0fdf7a126b51142a3968a78f956e3c7a0b7bf8b0b0a9c72c80c8eb9af6924d13a3ec75a96ac2c2e9359fd5c96d181d9b1975ddb0d374d58f639bcca6edb32ed827c3d44014d969881887a64daa7e808941f92d2f0183653bf9b686ec7809b72dc8261788cad76de6cd1573b69676dd119706d6e4c84956c3992259c2e80799cb7e70ec37ab6277501f4d406f32d7a249a14b08ac2615033f1a87640bb92217b5a02d7634bd8af328a9171019a3a3a664ba28b1c753c1c76b08b290fbd0b3fe0453d32dd98128c295ac8a5af99b9e190cfcd831ba11922d666b17c9669e7b1f096b19aa8a6d9fa97433ad0959caff89b3f1bb27f141ea1a220cb3066a480b3b368dc0c539361dd10ed325aa537d192ffee5110f416439a0b74b2be93bc06c944897eb104492cf6f6694e5f4008ebea4a9b819555912735f968d29e9a720399374547903abcfb634f0f066b1472c1ddf80168277f1c579ca0724c8436fbef3840d6e8ad5894d74b53e70e4af560fb1af4f3d076c8de513687b4a6dc64e00186d0176c8d08fd88fa808d12fee0a50862e83e44b576c96c2168a920f200e01ed4d488b796e22eaef467ac1e576fa53773aacbb9f4b371f3e4f7a30e2a385666e51306af7f7ef133a0ca612cdeb68ae2f64d9991303adb29726f9bf12d4c2967b3989d2972af9a748f372d5a159e8a84e9689176251de6010e577a2c273612c9fe8c87bdc053a34adf5b444a5653bda9624fa660e61e7e09c875978385d89be60e79783555d1d469ce241a0235b4e3b15d04e894d733801ccb2554e0303b4456a303bd4ca4aa8bf8d170820b1219d814bfcb86e4e1a208efa49c15943aaf44efa01bb76539c5bfb40d9ca208bd83e0d31206a362c894122d153d4a0a16138cc2a40f7a2a296494b750a243fffb9a07df34151d2093583cb331327bffa22027e692b6693c68c26526e66a27d7d2aa5f8b802e884822422d65e47bae80162a41d25e63ed5dcbd0f89bc83e32cbaf7c70ba0eda26035b52bfe49066e9f2ad4ecd370ad8c6808ef5becb99d7e40d6c2c59a1a86501be05a1479d6b7fde60f1ae25cfc03ca60be032637a9fa308e5d15d71b1a22b2adbff4901c83ed648cf77575ec2718fb47133810cafe67863c236b13066ba8238b0de3368243d66ac79e3bf93486cb6e02e3d06c45922c6a4cdec949a05afabe13db27c38e11a9174f51ddec429a5e908eb75ba7c6617f63db81a97270eb25752b3a4f7cbcb1c93d331a41cd3f25fd5e8d8630d42547d1b40befc0a5cd0ad11e4a783a6e943db48f1034a6a0d29ade4975ced3b6b28b4997e63d6887b52fbe8e87fad3cdd1b013ac4ee9adcb9ba015bec63828341d349e2921944bf6b9d2809253c7ca7e47e1c7268941a15f124bd8341b2e9031249811fc313b189c5330c2797b6a4f28a0d0fce7d4705885d464ec01be744ab0589a926be40f1fec2fb50fd479a39f2e7ad2743045345d1fa190e5382fbdb2973c19ff931f6b84eec5e7b4584a1d590a5f35ade4469da5ad3214bfa236f8dcb477eef791b2aa26936b99578207486e8ed5494363e60630db9d6b2e9fbb8acc0b0477530fd3f3616d6d8332cd99991a70e9d0da11fb92081da608400cc07f8629c688f964ac4ad52b112e28000a13a91427ccb114f40b16ae04963543ec76036a3d434eacb16acc6a859488a2587d38d8506ee1974e30eadd46820695291743917d6fd25b61d403a93e21ab0fd1e4ee43b2c72a3530d7eb9238c2e78d625f99070748eacd829e5dbb6f77ca1173f56651f1d293c30b5cbd5936ad1bfbf61043013e239a1ecf08392c24af30f32d57314e2732bbc61dff1c6d3a91c9497937ecb3ab6969e8d32090beee821cf94ac92e75bfa6c82ecfa98917db485f3c7a32a4f5c1fd002589516b0d892eec863a9c6e6c170d7826245a4d1ab870908c4159e6d1e8601b1360f0cbb214d60ce33156a99640b64ad96964bcb4aa072dfa5f4e9a2f89b3e1329c013ad1879e504d97ad2de39b7e0f68f328c92cee8c27275c8b9c6e38be3fc8b4cb495ab856b177fc9e116b909446b5e023840ca6794f4ad3b73557afe87cc3d9e9d39547c700726f57e6b5623be00984f69301a953eb018fc8527cc5a686bdce65e6b175425d6af7e593861ef09380eecdfb1de01b97df4aee85ba2c9634c716f1158c6f90c7024262e086d8abd9b0041bcf0b20f8de460217b5672704b9d5bab57c2275b070026ff76c115f120ca077f95029a07be6567f0a2511eb20f210e30cfd3b6b399fa5b6ac24aa01a245bca331492cf6ee5cb79dd3e4d041908ba5bd3c36a6ccc4491a895f62fecdf18adde121a2b0d54ab21dbfcc41b99a0a248d95155ef50c4493d799ecaca0a652193a7d8edd8eab05cd7526f49ef29cc4fc48ce9a3444899320dc134d63e0dc704b4915f94ac1ea6cb322a3a90e203acca733dc99eb1f09207da8087996f37f0a7420480848efe0dff1d7712508fa1b8d178eda4b05034e46a7328bb7debb9372f92cf4ea1a9dc7498221d181160e0f7dfb6243eb1f6d166356962024becfeee0f92eaca2f71b3e679bd1d955b83e255e4e7fff9e3cf382424f1a9eaec82fd45849743dd4cc99153e3a78111c49ea7ef69168e5aea01e2d50a753d6e3b334bb6ca43a9d404dbc461053211f0b4f35d6af4f18b1b8f2390f6276c36211b2c1e28feb6ccdf59a29c3f067df4ccb35e1c08024d2032df90f8a289cc469e9b1979ec398a62e9e5bce0c57f956f149b87c243b1309c2f69be50b15e58476472214a0c6fd40445f8d844d4e2193ec1b93a4c2fdf02d4073323d656b16a0ce120deea24acd70175d5b224ee9fc6f5de4785931fc3eb90940446442d21b004767f3658870137cd827bf519f13d80c8980b3a5cb66b6af93e1e133bd39b373b566059c0fee45293a4a7c9beaf2e9fc842b76338c641fbd36ca70e6653c1c75f2c12dd4d3733d4bf1ccf9479a82c73078a204f9f4f856f7d9f1e33b4c015d502411cf867e5911ca6d4a7666b1878d8c092daff07161f1f963073e626b52d4a4fe9034205f3d6fcd0f64d34c05b4a844567791ce1fab04ae738f268281e86e047372dfecb1e471cb950fdbff50926a1d6bbdc620626e1e6114b677c0c7cd899cce8ba7910e666bbe4c07692f16d9508f728dfcb2faf936c8e871ce695e03d604fb74b6c85ef0fe1f30bb0394c5c8190044bebd2bb918e53f5bb3e1fd4fb7653f40b2f148cb2b0909fb8407f77a797c3d9b28a1a470066270a6b8aaf836ad3c8e9a1d6ba01a97229da37d6b65b104b7fed96e675632652317f664312a7530fa89a3f0b30fe6aec3b3b61bfa04f28b91fad0f8cf3ef43c9a608cdfb12e488a4c23f990ca8248f76f9dff7c56906b197fdfeb76a8470b42cb022d3a254b01b4380a0a732ae0542a6f877cc6f6e439c80f2b8862e1f637dc243e3fbf8042b78dd74e0dfd504c4f8031577e2934e54b520d1c1bd18313957939ab2b62eeaf33361abd8eb87170e769902c78d9d2c0988b693502f70f94944e9d3f94c2c7777e6409986932a194c71570fa0e817ed2e7191f61ca4a8af3a5238b91f5ca0fff60335c80e182912048dc6139d5de95f86f89340e2aab23731c590d183290bce68b55fe7bdae3055d1c9373682a3e9cf7ef924b58fef251e1e82c1d04dd0127c312bee5e04fbd2470fa5e836189a58455197678435c6d1d2e3b28464a73d29da4b937ed26fa9c2961911c5771f0815d26ac039e5e633884911f7b182c37057c37058fce2e7c542cae32b8c2e358f76a440f1db4bdcd4b46899363373f56e212ee0d19ca01933d96db96480438d1be4111e315104e23507bcc0a62a8971911d43ffcce848f99c745a116238c21f708e57887025df3ab1e9e9b62dfcbaaaf42679d49b6aed875981c3c719dbef17ccd4620bd3f04484f8266afbda53cbfc8db5c4c54ef2d15d060a55eb8254fc3d6bbaa929b0552ae84bfaae40dc0bc63a27f1bc13c06bbbc0fc2cb50488b0e42ff182e3ef4d85e0725c4fe258e1a48ad6b7cf458e51841926787c9325bf4af7411abc5d15fc45ed77df0b0bfff12e20a5157d2785e79205203fd53f8c4a7e45df7d216e1ae33fbcf42c68c7a4538ff4c5f4558e545e4b11f6e081b7bc71af44e5324447f7f07535b1f50a0553b6dccfb85d491d07dede644b2821e9b84bb59ed9f7cb4eb003d5d350fadbe47955423c6a2f3a25fcfb75fa781f55068c19d38bdfaf5c9f03781de4cdba11ba01fb1b05cb973ac4d4a32fde9542bb57c7d09e64feb1cdf9c74c799e16da223d05980d8515fab45de650a4bc8e302aee02d73690786ab96173d7050d895dc3da8d96d72e6e7e889b36b98e1d6f3b47c7ce3de3f550ba350530255e9652b77ddac631cce1b602e54dcd54d50aabce83ced113412a282954c6c3ac526b9dfd4aaa3aac7f46c8ff93e1c01eb456ac36f222b5cd8c36d276ec4978e4b0730ae38cc3aa610861597536530737cfe4f2ed6c13f590639a763832d790810865194278a2abb25972e6e6d59f0b7a5bfde56b78cb998fc3374ee1835d5246217148d8f6be4c5d28c3f790360f08749725380671451422666cc365deabf8cd98acd942d8cd1aecb1866a7c0fe4ff5a0b31771dfd1a1281b9b4b59cbd40b0d50a40dc4b85bac68886458c95ab1f2d42356dcf0e45848f8ccfab69346b8f6dab3550de6c40d61f73f77bcdc5cf8aaf2e88fa439c267a8c3928bbdfb30976be158d343b1dd19793d802fbacdea4f548f5c8eb520c5de28321180add00283504ca89aedea864e51a9ccd90b3808f213a90e5be915082cd7acc3dc1287da79fba82a93d14e2c0157cdc8b7b851e60754c117bdae70c7de2decbb9a8698e4dab9eb45048bdbd66a771a84509857557ec7d862b9fbfccbebcbfa7b68eefa7b5caac42ff42610c3bc867027572f8a203186b3b8f0b049a2f9ba26733e0a69d69fef82c1ed32ec4b3a49afe23f419d800e8e927832250e966ce7bc7470adfb77a70e32bc74c547b27be7dc89194b5f69e0f23470dfec3efa129861d5cfefda07c4079c0ac0adccac701ce406e5e73c49bfadc8a4c25964756009bc313b97418180be2dd423e4f7808e8ad5cf02ad04f6b997c1d6576f67c12ef67a00cd0567ee34cc81671cc86150a090b70d8e89fda1f649f213f121f81f23730a1462da6d90064a5b73c85371e25326676eab3b73ad31c9b452574d48dd337f0dd40ae13688056a8f286331e5d3bf7ed76b80ba377f16a8d5bb6db04a83ce439226c43184f2f6a35377936ea75917ee558e53035fffcc1ee3c48f302bc2fda924413e4e2ca0bfebe9ba04c29dfb6b80d6017197891e7c3f64b521f88e91390c147e86dbdc89bba32df5dd0e1cefc8df02b5f6841baebef9214f1d2f04ff7132b74021dbe096d757763285a77260dce1b75971e01e10db14cc33e56569ebb5542b7b4041ca6540a14cb8cdceb13b180716d0ef5a57c10d736470dbed3f1a1ec75650cf4a17c1ad32c2b8d5313d7bc41d14f9cc3821e88e233906081395bbd1d1de236fa18bcbf7a274cae0e9bed97d34c7476ae1fa0eb4ea528193f5a57ba8ffc8d3de42af8ad2273fa4fb081327bb9f69c2bd7fd500ee92884ab5697043bf25f01794199b6e855c6b25c594557bdd60753e087d0bf5c1aa459e06744eb86483ebbeb5f9474af1a1d66e219ee67a004b05b16ff754c6d714f1a1c8ecb496901d2af35a726621ffd6f827386681a115dbed3070816dcb128501337317d21778cc8f226a2f941bac31027840e95d66e74a068e0f8aa49ed5d002cdd113c8830222ac6e58fc77754fc23890c1c9a19211325d59291eb353a059d589ff7a64819f70d91b44051d92baa647a548b64a8902e32d4be124d60a241b02846cc7c01dc9fc23d13cf4a748b449ab862b4529048365cc7b6d1484d2ecb2e6c85a1953c3fbd3103dddd1c1c050b12fa3b90e066e7b996da216ca2af99d8e0331355bf839f36630784ad4b753a4e888177c65819b6ac8e899bc648bdcc0bd3fb19848455e24233897b3e393a390e76f55ce569944a1e1bceefb0a732822e430565ebb0638536eb3a09a9b38fd70fa11d0bc2e2c9a29d0142d7c40e2f094cfed85828b868e1bc217d3b07039888961a0ab261e83ab0ddb09dc2b39fa452aeb73d26af4654470c83ae4ab500c93a8c9b773a3df4ae7805a304f664805a194f1686b4ec0f97a44aedc5f8654931f046d2c5d14d3b373607f4c7edabafd8e5ec48de20f3a9e01dd56b21a6c664be357816d3c6bd1df1b06c7c7f5eb6b9761adbf5ead20f36e13b8c7339b970a01fe603da5953076c424c617fbd59c2a6d48cb9849f246175809c8ed0afaa060d783f57b574160e68ee07ceb27264002d2d4555d81fc5abc9814b45c839021d7c128ed79c9fa1cf30f322a6a70860a7ce2879071480c2ff148b66e4182d5332280eaf03357f8ec92ba210c541de31c5153f87c5091750eb14f392250c09d1a60f664209d8afebdf65eadf50be9cca0216c51c32bcc9db5efc58ecef22c6b0b549741382f7dfe95223518f67b5f273cb36af53f8daa7b7ff1cba409225cdbae0c5c2f7d4aa83b8180eea038449e1649f81ceab1d1dbd50c942c6196e2280eaac71ae5f8ffb117dc9891678484578eeeb4272f3ac2b9d10d82a200849effee099fcebd58f0a28b049803ac5e8cc64ab1a18ed311ab24bd2c0c34453242effb9e715d34327637a9ac4756d0c7465d1360f98cf0697873442ba9b1f81c20c5b14689034fbcad17c6ec5f9ee2e4390d0171060947d2ac9b518ddfc9c0a7060464225f78deac9688bb59ffa1916c64b959954f536bc4af3e9d81756b84d0aa78e118d70f8c7a8391a3510e2ce5016a49f7438d3a1367724a337a6a9aa4c4abfdbabbaefb804ed8a24b7b47a5f57f4ce76b608f0c42cb48385a59b47c39c3755bef052ceb3dec426b6ad6ec86e94fcfaaac1925de2342cd47fd488e663872ddf82d685c235fa9c1ca7ad3ab13d10becae45a6dc40823edb0d980d9d0d3bb077415f9862f538702cd60f3ad6f13f065c09bb0f35055a33dadb93feaa754df2efca0de21c9b81bcae7f13ce3bff03c3d4d3a4f42b86d80124c415c397ece04887e91c830555c7847b8865249e61aa7b90e886645994374f23e5da1bb3d220db5cef3548fbd3778871a2ac2415afc007c0270363f782d98bba4ca7ae154d791ab21c922fe8593e6d6ad09bc8eb5b70c8fcd978ec07ec0f4b1b31fd79a05f6cf19127a67510a775d8eb3817e8661ddf0191f495910fd8f0bf3a58019d1e055c54d7eff5e48709d6fa8b8be697f0d2548d74467d07dd018b29706f0ade8e970ab41c981dee5251b2aa40aa78770de619d05f432906dfc0780f1bd29462da22a1424c34965a5f7cd3d34b693cdaa60cc9b75743c2f8315e6aadf802a99fd318f679774bd62e67e1621f71e92e0553cb5c97a7af82fd5adba3d12c12c5f6c5969a32ac561d2399acb326d481abca76f4203f50895cb788ab4ad152ac9e8c301e79ef02d0e0232390329d951fe282c8359578413eb97ae966a8e9677b2b226bf376003c7ad534f954dd5e88aac0d52fb8bebd285403268e49f68ed79b865f85b088841c432c0018922208d3022740ebcea29a0ceb50b9479f12227d53a517583851f335fc3dcd22e56bef60677e04193238c40eb7d9a4073d4acfd15c97579542b8c3a6c02605f6bf664b1f7fcb790ccdb4e5cf820f754a79243713352f069e811fa0af6bc5bef6d2d3d17527108d08e5958532c5bc58f441a5d5737207692cced868a2bafe87fef1c34053cd4d881915d1179a1dce797e37d9f0884ec9ccc4ddfdd3f501de738e257ee8fa2168ae4ca2525dc3f4e8eb1ad2d81adbf0c20a84b0a144c0a79d3fde29727ef912745e71b1d4f46085355751d54e632f12f24f945fb08f47d86dc26fd67bd368334c39e9cef613a040560f7c5747356810b7c35085274ebfff6bee1533964a2127758402d88e4ba7095b4f205c3a8d9db2fbab70231c5d91a15dbb29a59f49fa111daea5c59e69961eb008773d4c65ceeea86717d3e1f08694dcd446d2ae873f09ff6835d563694d4c81ae8232f5c364924dc03615288bc31ae527d0bed01f403481eac0068ee21d551069979d66062f01ca39df0fee1b7e2c631637a3084575978aebbb1cde2669aa623555d4da975da857e74c1985ea29d0c094ef21f88d9a90e0cf8d9b37bcb711dce6557587bd1ee12ccc2070144d7200725ebd162e78bb81cf624d8b0a25f4d0b5f640c0447da02166cd257d447e1729f26573d02b2e602a49c59f17e2e410c4b2d0cd4c9e8233e8e15e330fae71a5161d10d3511c995af42245a5936838dea44b139f514f52e40ca2bd19ae5f88bfed4609e2c84af1607c987a7fe1a1b35359eb6ee025c89480ad73cdc50a0f42cac0d034bbe1d89c9ab36644116175909d55bf1b6b1f22927a510b4f00b5349dd10ecf3a7455fa456d276199aa92664a3f3c1e109f25e462636391fc283d2ba8ac4b74591f260e4a4ec1c7c291825204a3631ab1257ab3ab9f07ffc4cb0b836f0b7bfebfaf61712f4f4ea11e0c53cf1ab5fafef80efbcc912a4f98175d0816280000b321714a3d429bff540bcd446945a91aced2401dec34920af027d1e2614012faf0aab229b7572388bf4d0dbf26b4587a9ac9ded6528f24b369181d1a54a3810790570f565cadd2d2c9bf4841e57bce0094c6088dcee640a62e106a124e515e9dd4512a3fa1c30c03289fff8f887ce9b40f6609adae85d6b22742ec68d70772c2246cb8a5a54a8200c3dfc30fad147534f800ee24783ee4403e3a1b5945a1c942c33d8ad6fd33b9c63d8808df2b87e692fc5d7ea8a70e941f5277a80c3f82ddbbfc103cd9fc5f0dc5685dca3bd172315ac1d86f746042ba5aa54d101e3cb8eafb1bc6fbdfc1f4e4898aff501301af5d071147be0fc1803c81e8e12302ce77afc073760775c1f799502f4d7fcfe7de2bd0a3ee961b9517979baae50955b3c78159f151e4f404428f7aaf537c3c53ee948376809176f3a8210ad96a320385eccb881956c5449b5290b81be52c7cec5e0cca5d5ad94f04a3cfbf2003bc9a6f7a528aa9c4bf6530b6e6b8f3493fc4a5ce0285d49a78722de2d4583c8dfab644d5df9c9861ca61004c215a0a624224c024ed02de1b1a1901257d60e6ae3b070c385447398f83147938f500c2a92f2a2407662d8e5a892272a148927170aee7a78f42d46b2f1f790b04a5895114456b0ae5dce3a5cf2c910ac2552222191d5559ccb25982c54de0f202f82ec9ff66412ccc359babf60b8f50ba8e304189c5c91668fc15e20913890e18503be7f7a6b2c77b32cf5a216f8fa7bd10c0c23ae2ad13c3df22b5549a86fcc3b7c71ba26ac2240ed621ae647dff4671f03aa338902d95be0732f42ed37cb6ad80e454bf5c9c7bbc15ebeba9124013bc119b062890a6d7543a50301f00f7129c53b43206e805c8250bbfab52b6314523ba2f538f97fca1215065f525a8427c331b348907789012eb73d3bba54c390500e615236a779cb3c37025d4a0c80662fcba835794717966e4d700ddd61b218c41df27290df68ad56f8b5b7745ee258a8200a4fc2a2a25d8db1545704a4690d43e2de486536ba2dd65d56856a9bdb41b01570738387ecb3c57f5d30dcf0ab4d0f1552cb473a2dd4f23061f4e2e828d7b48c75a116f84ef796d22de4b20a30556cda98ecb940f1dbc01b887ccc72c1d963fbcfecb96a82648ac772a0f491fd3bb2dbe70da579e224d8aa4de901fba9c59ae2d6913fa3b2a78c223f10d791e9a39d3af2d882668ef187ee116ed1bd8c3a37c96aee50f57ff4b3f6d1af9ebf1885f993fda5273177e37f4ebcce21f9b257a3d7cf408c4afa1360a4e3ac1756190e14eee19efb05f8a92631f510927b7bd75f691d0655ce227b5d58bd53f135781fd09bc872d68c46542874496a92bb36e662c74df10975d1148d7170aa846f986aff617abe089610723a4f9b763ee505f22ed64686223507bd3d1da37f0bfb5e2ae6ad55bcea3c0e9165828d041917c47e29afb65b13133952e7e2f93ada811784acecd293a45504986b155859b9412cbec26a3fc4f4ab7f4cfe42b55d001a0061a447b2559fad6b0f3f125c4063f2d87ad0011086cc7ffa994a64ec905b1a5bb959fb9cc7e7cc1c62efbfda9ec8bdfc65d9a50237e0a5b04c25942b6ac1d360a5a66942555cfbb6795340176e1e488541a4cc2757b484dd96738f808c336f09c778fc8b710d596341668d2cc59f76e5b0b7e09e145b694a39b4786cf639740ef84bd9879511a518c12e3e9ca2bf3943a63b539e87e6b654556540208cc1d3db75860192f84989be4acd777524a0f23c788cd36ea23c82d051c48847902a6f42a6cfaac53a4831419109a89624c2f88535271d4ee745c97177b369dd1f2537da235a51d65e06ca91cb9474fa416948a48350854a7e9dffa4ae97ffc7485dcb14f8a94a82e688c0f999352de765e932bb2b55546a6fab69e92ef9a1e0a2324dd5cf78a9805b55b212d5ed327c79394561eda9552a16b2421eea74192497050a484f1db607371e798626e919c83580c153412480ee0cfedb2f81cc0db8620e4ee1640a4e601f646a99b3752934a220f117d1135107c59d111d9187919ee88fe5569d7b229ada005eb89518aedc2f963b1a0d5d13c98b7d2179653544f43e47a2e3bbc0688e817256686d7b092eedbd81f013c30191982ca5dd50a4b0051164f556d521d631416a61b02202372e8171b82be9ff49a8380160a78c6e90189bec8c4fe145d93bbeb43a9d29fb1334557bd6ce874edce867efd9321553ab18f0069c0f8b0ae403d98439eccfec43346f9d49ab21c0f03fefed20febcafe8802ab592c39e3a5f00eebb3e8bd6e7d34e5252898d39cfb6331d5cb47dd9f689de3438ba91e642fd03027400d23ced1862d80daa012cde4246a86ba5aca3e266680a0b5b47f20d518f478bee2e76053bb3444ac28cdd61a519d08c97aca2a3dbb156f74655a5c18a2d4e72bbfd1dda6262127a5eaf00c10a1750824ace1af9bc5d2143cf1a98e0103a96c8edfddd4896117a36b12470abc9e8517f9ca1b27fa54874b6f7e5124a2a6e5e64a14275cd35bb440ed3c7efb978dda422dd627d556ab2489000ace53ee85fe989cea2362dbb71aa51a4853237746be4441b4818fec916d50a3a275609811d70e7c7f58b0aa0893f305029b9f341df703f0be01b38210274f333408e02ddd286f4cebab6b7aa3c205bfb5bc881fe3a84c40025d385dd3fb054b691f7e496b67e10d6bd9d52d0098f6ea9d5cc2b598410800348a7374540d596ca025302885f166fc0d74e5d84f842c3b9e6f6c5c61f6702f1ea6bbe3c96fd7932dde4ebc59b37721311bf4a1b5692bd0357604180d4e379c33568b300e2a5e27b5995b538697a2658acec19cb44d6d2d33a0ee679814a5fd9d7dfa6eda62e22137124c7ca3d6f9ebb4010c41742a4988ddc3f99799bd712ba82b70136f44083eef0af0e81df4f9735b9da339de8ca59124b705a57c9988a96c25a6a157bdd4fd1e6d8be6f9e29a87ad936a5bc70f3d532d98792a3b511d3dac70c0e0a0659653566d84f11a46481d0776fa75bad8fdb0fac402b38cc02a0244a44523c2dd540643b28f81ffd0a07a28e502c7b50831058ed4d087049e7471f1cfcf8aea2c3b74f6776bdfa80d8c621a9b8f63fab54c126ef9380ebe622d011c1b0e3c52bce44aede5311d9b5ffe7f2075ac6f56e91d2f79e1f1fa55f4cc46af7f9a0f29f0023270cb9d89c4b0737c103596b626c72909e2daf8b28923a4cef8e7d7a9da6cc51173d7611090152d3b5019da94998221b73fe996483871699c87ab163e00bf14c829cf6604013c28bfc2735083732abd2370e4f6d11a5f096e0d4e02ebae75c922dda2feda2b13acdb85530f8be229bdd3415ba0f9db5226d3c5346e4804793f0d11059bbccf37691e0526555c3ded36d565e99388fef8b207b62c835e700a5306e665c91d0f37da3f69555eb2684278a9ab8851942e8ff00449d09cdc73c5b4528a79096cae05fe2ec551105210785535e940a6338c38c61562f61c93617df133a3b7f9780c3bc61562747a387a8bdf652c231ac2e0bb3082271c280477085e401b266a8afe15f872f90d6a7b393f6cf2f5cdac575b4288344208d95bee1dae0f3c11d10f605f8b8f1aa92db1ec361cb6bf9dd2217a8d4e8dd651cb7d317c5f87c73b77ec8e11cf931226f338f33ed29977bad3224fc3bc5209531e3aa333cac3e52d539fd24cc6343da2afb65ab0e346073bd2994f6e59bffa48a32179c63a610817998e7209e522f761239ded344c96c109438ee458956d3e5448ee32e451f5863c52f0fb4aa5effb6e7d588b986e11cb73998947333181866d2648c144a22f167432b03858f5404e2421641f24e4ee19b0deb40624c87dfa3371f415f38736eabee206b91b8b89446354c68ce278a41eba62e2e8272a3cc6a4f028d291ce2a06f1d759daef3d44639b4f3f9938b625f3877ec7882b3c8a5fc1e3572b9b8247ab1aca4f72ff03ab14bfef9b0f8d81db12f07d296f3861666886104cd0076e4b728f3a72b649ca980f17b19fe14d0a6317bb63a4742a64acc87d7b5ba86df44bb7839cd87e07350a3340c9122df69368b18b8695de45782eb36762ea4bcbdd74b721fdea8d49ee0eebbfbafd741d1e73c0fcddedc7e7dbb10da13bfdeaf0d43b0d6f3cdc63f86d3e20a63319def86c43b69f5a6bebc34e80b991805d063bf650118be90e9d65c10e71ef70c7c452c670ef215cc484e47bb7d86d88f70ee9adb5c33c2d762dbb63e46b752897d962c16e3e2d32b10d69f1fb18fe863c26d062e30e71134cb4d8d2a88991e60d5729865004c920b8fde4de7c581605cb3c6e3e79c786e14710531e256ccdaded269ccd663290f5e9ac61e1cd90104851e671c50beb06f992f9460668902f99c37adb30efdf4bb787f775600d433c6d2b7321f8c46e49346c7b7f0906c87428d7d2d809632b4dd8ce30fc774ba5d23b994b977bbd74d675d6aababc1981b595d4f65dc36aa5b5cb30942b38a3311dd968e7b8a24f222cc09475f4a5dda67924fd821d3b1e49f8c93f3a6f60957fac72bf85a39d5eab7535aef2d8e5dad1aacd21dab3bd6edbd6ab151e378cbbca28ae79520135bf77ff6ad5641a8fe0b59087973bed5f2773f73aab984d1ad6dd68b7b6284b280f4ddff77d3f6e3a7d9fe94399ce5d8647a0301e3b9b6ed3dde77db466ed5d9d756a739c483db84f91b53bd23cbfcf4ce73b3aebc7cd2a268efa1f789c4d4cddbca675b887e9dc353c6a4d32d5f04839cea471136bdfeb51fe7d1a1e71e6b56be79938b477b8764d7235e11055b5d4ecc070c77c0fd4bff00830cf2e853d6d6a47b515f93369f9db4c2693c9f47193870b77cc974eaf76baf5db05352c3bc4a7afb628b80b270e4d601575cc0127feb010dac9d0fe38dce116f77afad3984cd781f9fb980366d3c38f7e9c424c9dccdb84c3f1079d5578b87465a7695a77b5dbb5d8c5eceb356d36c9cd4d9daaa9d0e173120429d3fb8cb4274b3971e7d09e3c2f93b27ca245793a9b049fbcecc06ddb428edb368edb361ff5eb3a367f7c74597bb7866fbe95e47ecb97acda953b0993a2d9824f5ec2cc59ec7ac0f6a097799c33334821cf232608b2c4e39c657a7981541e28a3ce58dfc2f172c550a0647999850aca0bc4cecbb724264227cb0799b22b34a093e58d482c5b9ce1944ee52ba55d875b3cbc77dfe1bdebae934b73bea3739b5727d3772d4daa93e594afe7dee970d80197ce210b355831b7888334c2ca245e10d205a4fca1d03711f771f4f4ce1b5899840a44f278790f048af9458cf6be16de4c8ab74b4aa1e032c5a3fcc65d294f60122f14c9dfcc72e8044179d5626739740220e4558b354b1943f1102d763dbd33d70bc5fc221b2163ba8821b9cb7388bd4fa65ce0c9230d1776323d8dac9143ac4cb2052739cb245b40ca3643146144964a4e00003b4aa2dc367d99640b45b12a93446f1a9999a4680db92f44a3a0412f0cc93daa1ad6e2417b480c0597eb294ee2851a588128cbe650f07d5e49e7afccb5ca50ce26f975a397576bc9cf26b9adc836fdcdcbd33bbfdd2aa6c4f37eb389a45252cdc82761b6dbe6051b46444323664dca9905dbe7eed865bacdfa19e2964554a8ffc6ae851a56e3c850c3682069580d11cd1bc761873d00dda46137deb1c7de396cc7cce81e9a079afc5146f651cca0003e3e83427c5c65d0826068bbdc63eab2c9665367f371f58b7289e26273ab9e584e00f8d8e5930666c16eefa3cfedab193ceae499cf79296fe38e3a4bc8366edc7c0442c7c7d78e8f77888f2c381f4f44f090e771a77ccd137171eefc1057cad78e2be54bc79dbfb9f3da8d1b1bb7a1333776796fdcc6cd9159e4d8697873e3df8d3bed8d8dcb503617b888f61adac0320b9991d8657813c3dd84f6d09806c47fc063e703ee89d1b4193de0d1ce380fb8870771495f78b442e07125003c5e864731e35126cbc0234d1e69d1b6ed80c7958dd1937b058383f02f1ebbe3d1dae000dc5ed2e27618b79920d118d7435f3da3310ae32e2d18a9855b6761160c8020700e1c1795c4c24e61b0cbf0068667be7167de683e5f5383a7a5b94653438391d4f4911637181e7532ecf3cedcf1893c73d9309ac7a47ceca29258f9d86fdcc61d6db6f14f0b6f6ee069a5bc71a78d5fd9a28dc76e6dd1c66d28ecd2f8bc35fed5f0a6069e7666c6c6364383068d1a34700b815e58d9e248b7ed40e0ed325ad0f61f8272cf26f2b56df7016f8fd18ab6cfe86b48343689c8d7f6ed3d60a4ed3c60a4ed2fbc5d657bca76d516b47dbbb87d073cdaed32f0b8ea6f45343601f9da2e847c6ddb636cdb61b6ed2e5cb45d8c849136987e6daff2b53d47de0e038fab6d7b0bdedee282b6b382587050f70dcfafaebc0d95f42a777c1e35a451cca38634cae45143a2c9a376ea66e43ecaed02ec2e720bc97d05e5b4b746433a05a7138029a60ead2b62f824ccc84dc1d2b4d89f69b187d71ba99dcc9829d2fa944999981f3eaeb23cd7a5d098e964b0d5880bf0de05b54f63cd14f81d6ed31e2a890d95d8107b3a79d4c93b3c35aafc47e71e39b20b793c9de539b20b79658717581ffa4996bfdc99eb4fc3585afe22e3ab15188f01f315eba5b3eea23f7d3f9d858f08ef9d75d7877142ec61d64f77ddcbba779e52de27113006e0615412d1f3bef2f2969787ff34d0754f675d8c5ffa0c8f38e196f7d3ef5d2fdd96f7f952cbc338f3f794a6502894a67d5f8af5b1b4abb2d6aa582cd54dfd2bfdde510a21a9ea95704e3b115fc32360dcc33d60fcc33d56c61c959fee18c2b86be52a3bdc93817f0f8f317085c13f686e31a2e52f2f2d2f2f1a077a2f2d789462035f5efee2bd6096bffabc5c96afee596ed3f5e7e5edbdbefcff5e6efda93e2f1fabcfefea32d4f1729b76d9e1f5df2c5d755d5ec31b977f1e3e0cd6f1bd67b93e4a2124bb3eadb5dac1efd00e82e049a53a3d75a98b7559b7a1acdb19df99f19d19c6bd6735eb88d17b0a0bd5e98e3ab94110eff80e86575dd4ad4e0e7f74466107cc1f54b7a157b188a45293562d05a6264e5d7a31ebba5ca5c5e5d5a5e5b64a354710fce77dde41e93d751bead92b73ea8277fc0ec44faad777c86387d7d77f4d3ffca3738eec42aee7e15f054bb7f628bdfef3bc87d72ab163e99f771efedd1ef59d656895d8d1033e7954b957aff25127d7995d5c6e435dee0e5fdd9a79b82307886495037147298464952a3efc4b7823e2693dafe639db89ccc80ea7214e4ade01f738bdf42e6a58497552a94e27954a157e94c5425d95caa65d1665efe9ce8c4261d50d6f542d1edfb5eff8aee1aa8136d5d96207cc1f40d6c17bfa478bb2875157b90d453169b12b17b607cb57b831d8ca64ae5adeffe98e51e493aa73ea1ad60ea64ed7aeb4aa1ee1552ad53ccdffa0390c7166b27719a197f404ac5c84aed2e9ded566a5c378757978c4afda3fcf0baf81d73e7bc7d4e75120f8fddab5b70fafdd318aac7d864778b8a5ba17866014d9bb96bacb1033a3c6f016d35ff6405d857bb81ea6ae4733caf5161c178681590ff1f8822bc63f682e1951fae9344e914fe1bd7fde0dbdd3774ffbe781e0c908af8447294ae089563cb2fee3e251279ff03deb948637f4a77b5f2feb5e3cce7caaa7b3fe9dae36ab49a7b374d427b4e5e0bf493fd43f7bbdd05eef9f0a8f51e4b0848b6cb72da2ee5d8647c8165178d4700f7a90e25127c6bf2b8d287997e117be7e781cefe7437b9606de2bfdbbaa3b3e91551f7fa09ed8008002009ecb50b0ec570a8f4172f842e1318a796fa1e0bef8e28b3a009959bbb7710f8f47cb415066f01af0521fa3c0d12e4847d561fe4466e1711efca42d30776c22cfc7b82e778c22cfd7246dd6c7d3cac03ffab7e60e71ba9eece1b188dc63c6bfb7602766f258c4573487ace4510e4b7059f83924a7ae7dc66766dcbb93cee4141e8bc820ce99c9ab6b3fe814ec0e67bd7ec66ddd5bfcb150496c0f96dbabfc9b60ea5fa7bcd46d9ae58e33b37861ca4ba53a54eaa86ea24aa57aad894de13147c55e142af4422ffcbcd0f33ed41d29c87265fe569ebaa1131b7a966b623d951d2b473d75516759c9983eb8058b7aea5d47917efae9a31d571c50c35057bb4aa5fabeef3b64fe306a0af6d3c9deb55bcfe26dfea0dd86dab48a75ae8945e1d4552e592b329feeb835b997b2ed1cd04ec768d0d6a43726cd09517ddc9ea43e6e4ec6ad8bdc1b173b7cdc8c721b2589bf452a3cae5645434219100bd1220d12a25ffd7b6dc4603d4fab499e57f49d0b830d71eb303e56b4286a3c1a1e57965a0e0c9633b249f73087052b1fde12591f1e33a3459b16e7f7c39579fe707fe0e1365df327c52bd3e2511f6a8587694fccfde1fa20f2f0612fc4dec5802c62f9e75d1696ebba8e99ef6d9ae533dcc172ef3e5c99636ea8ed68b335f0e4ceb3dc17a29148220c5730316474f8da30d7c3770dc30f0f36ece521febeefc39dd4490debd3782385b793ae60c38f8de4a46bd2123bfed0f2cb7f28c24688216832103219083103f10c440c206400b1020410976107c9989e4f90d290548b82668e713275cc1cb6174169b8a2dd9083a81c8cba402aeab04f4fa1a659116a5a78ad45b520223424d5e187480d4aa8acaf7d61072131e3dd83dc2f0247a321ce8cbffce531f7e1334cb5d8b7e92f75a70e7bd5b5d3b58377046f4b475dbbea5634581ff6aa830f4f782ce113ea74faf30903a1397cf8effa8082cb293c5a0c05074514b9870affa039855b38cfa93fa730109a3f9c2ef5dd1fbc30ae69e0982ea156c0b8b4880d569bb5288a2da71f6b92ebb78b30109a5dd7b32b975486cc69648868aeebd616bde3dbb5e8fde5822d7ae27db833af5c202e8da4063f10d4665251174ab49904b5afc5cfd03b8b788ad430b0a34f72f7772034b734523b496a986cad8bbaa861df67dcaec530c436624b8b135ff1cab438f37156b0634d62799ee7596bcf55c1f6b080b5ef41e6d69f16a34802069b211a36caa1991bf5be100dab498c7e82d03e7e40c1e5f033a7f0b8019a433caa1e1a111ebc4d572e1a065ef67014132034b75c75a1e072cb0f9aed7d5a2cb2273ca3c599faac4693a345666625ce501dc6ae5a541e98bdf0fbb4d7539e0d4dddbb3d5c861f8682cbafabf0487be8a1bdd73bdcf17afd9b600fb7667b6596e10b6b3330490a7694f176d8c1bbe7799ee779d7e5797dc485379ee7d5ba799ee7799e775d9eeb56cf0bc330f442cff33ccf0bc330f4bc0e322cecbc89858595bd31745d57e240ed86b5d45e076a17cc294c1a86abe77d2550bb5fee135c7c8491e80ba7a4c0b84b2e93cbc535ba4d5e5e9cbc20bd1cbd30217a316a25d117fd89341d5c57e429076ccf4080d251a3e0760a2e9531f5dd73eb937bf2e2b2cc017fb9360c74fd68b714be10750bef601e2c04f7602b5a4ee43ff77969f262f4c2e4a5e83c2f492f47eff9ec05c9c5c545bb5dc9049eac85603348eaea61ddd426ed72282828daddacb5dad55a26e0c555a9729e5c103c9dbc93762bf82305f7fb36d028b89ed765edd21fa0202c5a14a22ffa54a8a366d7cf153c20adddce2b31b8886114a3498ca3185dac5c4f5c492e24d71197508b4fae0bc865e42a720db98e5c4c5c442c2c2c5abd52bec210a773fd501947acab5c1512a024bb815f88c0aa06fb42046a77767d82fb3224e4be1099e0be14d1d72ca33eb25471615c51820b2388e7c2c082041786101517c6911669ea3d82dba264e7b688e0b60cd1578b90165b785a6c9985e0b60481e0b6f4ecb6f47c215407a04c3fe9d0e2a3ba870502948ee693d3bf0cd194a7840428c9e693924fa73cf1620e7248e1a255420250d90dbce295ac097f893bdbf0e9e422e0d30d5789d7b8ad17221e76745d87c3464db7c415309d7cbaa166c6e1130e9f6d986ff84cb2712a4459cd5f8868ccf5d3e15b0a757cb90c33e9528008f9aadf710f10873be170df70a71b2e0f4e6c944aa51a57014b944a3bee01bab0a40a66c8f51420e20c2e8801c246103cccb899d12209119440c0b551e321e04e2757e24e37ecb8465c61876725d3712a44d90e1556a6a4c66c431b5e63a3c66766bee35488321d58265f15478efb8ad5b83b66f0b551f3815c7893e3ce321cc79d47afb9330dbf71a7181ebb730c87dd4986ebb8530ddf71e71a3e9bdc255ee3b2b28dbb837423930dbf67f8cc44c377a810cd702a6464466617f8fb6adc082fc4a9398797c3881a346a6e7821ce3d0a0523b0e10a408adfcdf7b1e1de205d9c355c23d470eb979060b0519bd008030d8eca408631d0b841481b9546cd8d83da05d265fc99861a2720a18b2b0034c40efb3c038de37818e274be0f431e9da7199a9084ac5dd95119c830861a3960b18bc5808346cd8d30a4b9330c77dd09862f7167936b777ee1623012c3bf190630187d0105db8b3513eec29b1b7732b9eb4e2d9ce6ce2dbcc665c934b090857f730b777ae1530b7776e1330b7772e19309174cfe4d2f74810b2e7c5800b140b314edfa37bf9e5bd0c2750131b9ae2bb2808583a10e2f6f58b80d7e614f3abb54e3aeb2171eb165dc5e7893e34ea2d7dcb9c563773ee1b03ba1701b7746e1337726798dbb92eff581e3fad042c9bf7ab7cc831244578614b5b8588a35383583f30a4baaf07a352b5c618915aa604209c39b7012dd49854f28dc59f4a9e44e29bcde9ae713ee9cc213f0fd26158aa67065db985240d1c24e2dae97695c3770c46a4c268a32b7b83b406c318d1881e3393e93dc1d9b598d2a6dd4e3538853f354329518713ad588f18aa9cf71310e98202ebe330a77c7488e5371998d4f255a7c6e51f3d8a91065466612d86766922444b07175481bf5538bfb22ba3150b8403ce1d6e3b832666e9636ea614ec815c7138e204301588a34ae1b386235a810a7e23cf581df50164a58421390bcc65549c21126380125094c58c211272841095924e1c8d010922528210b6b9b6099606d128e9c4ea7241c41a1504938924aa5b248c2d0119512542a956a0929294a4849424a4a128ea8a8a8ac80618e3b89701c7716e135776271d79d4378ec4e237ce6ce23bcc64db92184201c76778c4c2124fceb6c49084243a0c148c0e2eeb882da06c582cbae1f1963cbf015e1ebf64184e30d0752a41f693ed5e838c2a5215fae9fcf215c16172c6e8c22dc1829d6e30b84115c76dd85838c0770c22e239c844e27aaa150a88a4aa5521a55a95445b845684e049acf203476008b5501947c75a89494eda64c5605867055544694142bca092c54a6105454429c3a85108486b9e44a88d37940b6bbea4a26fcd014fae0074140788dab3a0121e8073e40a152a61c77f2e038eeecc16beebce237ee34f21a379569dc17a297cf755f96b428c117225943b3912bae2b88f6e0ba8478705d475aa477353ec5aea01665b0b5eba588be10bd6821b7d476f11bc504de3b2d0a2ad39cc21b1ad8f513049445016beeccc16fdc3983d7b8a77caf0fed3e7ed83c89fcc7a4c1695c1f50cc2f72fd68eedc01900eaedd2eb203a0223a48a9face1bdc75a70d3e6770e7cfeb9d38b806a4cb13079f39b83b2208c017b3063307ff260deecc93c8a5f287fa8983abddc0063f37a506b786ea4b91b34d9306540a1adca6b973c85d77cae0f84e18cc19dc1d23330633f837874c195cd7153180414aa8c3cb55a552293aa5a7a4270b5a1aa8538d6b69a454a81c77aee038ee7cc16bee64c16fdc69c55d77b6e0352ecaf4398deba3bae05ff579c10bee12a23100c857cdf11df809b97e740d652a852064ed13966becfae00200c8b2f6697d28408ecb030f4ac828b5e09eacb8292c50853855b502d58eeb1aa22f9529db849f428139ee24c171dc5982d7dcb9f31b778ee0ae3ba978ecce2a0ebbf304af714d99c6f5e1e2f90e15a2ccc834c1a9f814f2cf754b79c3293bb26d5471d7edb26bf2dcab8437960c325c17ab6015d7e5f28657a8b853059f23b8b3e7d30477a2e0aebbe5b973778ccc145c044fcc9d7f5305d745a4e7ba8052705d412870e140c6d0bb6c207fa06711825d3f2c39db742fe47a99eb40d62e5eb9ae8659582ed7a5b8e5badd42c3d5e2ba739ee0ca1062825b844794ddf8ac6296a0043c24b858a36204f7b443c3e5ba727b51a5c01c778ae038ee0cc16baece5d778ad7b8619eb121c52708fe7dde8a6bcb7805765d3f5423d230dc301ca70780ac468ab18f2ea04cf3d105821a1d598349b13e7665c8573dcd8511616528004bb1aeeead3ec88011513aa5b8c4b03258444031c658678280c5d2b014330433047701d158ecf4ae201aa3e1faa131d80481a531006d8a1bce745ad7b6cd34051029eeb679a061a4a8401c9703afb951fcc6f5c05df703a7b9415ee3821d08f2010f74208a2856429ce78d032b5306f980073a1045143214c00116964a0a587381fcc6f571d7d5c069ee8fd7b85fdec0b6faa1011f1b00028465b6b0c21b5688730ae4eedcb8cd0cc837f0ddb8ff5ce46c13be71a5ccd5002c637e68c0c74db9c1d8012d2b2aa0eb42f11ad7cbf8091cafaee3b8a6ecba3ef2772fcd4fb02a0d168eeb65d70592af94e27deb621a4fb478b8a505c74565d775028a2ba5e832f978e27a1e904d8a345c60e0af56c01c3703c7712df09a7b81dfb8e36337e7b0ebc46ddc1e9fb918788d5bca34b795d4326b91be897ff86eb9f5a463374ec7ebe1e31bb7e5ab9e15e274f96a30227c68f9500019292e31b656e924430119688538b565d630d7e95b490dbba76f3d69188d53938fac79aee35b3d20dbd612e2540b5c1f345c3f399707d75d429c8e07259c182f40c3650497f15d3f2ef87676e262e0ba72aea4af1e2ea14c5f88de047e3d8c90005466c760c70b58e085687c218281efc40ef87881262c6081b792688c86b97e6c99657afc8bcf12dedc7f2b10c79dc06b2e057ee346e0ae2b81d3dc1d234c54e010788ddbe5af5eaed50a71beb5b48438d73213b7c88d57e0c6295043810948200210a8b93437c4a94cdc6da3512f7d09716abd4de3db0d716abd326f345cf82c16b0019701af71b9fc805b4401778002525249993e6588c65298d0177d3774a58b4b830cb80df8bdadb9c0fc2e2e4d9fc284c66424d1174d6192c224d3ca805ba558278c96d50a068c1750da04fc25bc29a2807f34e441330eb20005dc04a8ac25ca3292688c2588bee86935d58a3f5a194999cefa5c59281f5941999e068debba825aa4bf715d58f48bbee6ba705c179216e9735c17d112d785800bb3d322bd121786a7457ad875cd5c1717fda2df715d5df48b3eb624d3db6892e9755cd9afd1e524d3b304598c472b3596a0dae4b8c50269dc03bce622f11bb700775d039ce626f11a77cb9700fff0ed9cc47d51d22f7a97f0e600f8a5885ecda5d1d0b403fcabf7e500f785280db67e7c21ca2f4a5c3fda69e071452f3e28ed01fe873707f8c39b895f941cf1acd9f40b51c30e70fa17252f45aef0e600f80077e2d7570c44c3187409bb1629be321f20090314800048b8481b1509182ff7b7a5056217917ed1df2bb34b7873040d028c958ba426238e38cd1dc0ef9db9c6d5721be1d2026e17468d5b330c182e608d4b330d9abbe3026a1bd8f573645fc232d0dc9636364fbe2aca899710c7e6fb9710ff050698e3de1cc715c08bb83acee3ee381177e6357cdcffe832be8d2bc410a7a29389607e213382f34fc72de23b2e8f7f3397887ff7965cae09dedb59182e06be5bcef11a32706ae4b8326468f9de1d76d0401a346a16450ebc97e6994b43beea716e119e4e26c487b83c5656f3a23180d7abf38e2b93af7a1d37098effe872157c70039b890971f1f5f1c3e67b1ae721c4b119eb2801c7a571efe521c4390f1d78efeca1871278afccb08b633ce47a015c1f504c31cb02f83d8d01d0b86ed4dc7b67843876464ca9e33c13fe5f401c37bfe6ca7ee302e0ae1b80d35c9bd7b833dfeba3fe479783f8576f671ab714a604b1c91fea657767878acba404628c91ebafb4517188f32de3cd03346e4bb1e62bbb3b2278b9ecc6692e022666b24ce36a36b714807b92623d006e8a7cd50741735da48dfa1b574a20c69beb61429c7affc5c06f7c0fe6b83c1cc7ede13577c66f5c1977dd1d4e735f8fdd1f0ebb40dcc6f5e13357e635aecc34ae0ffc1f5d8ef987af9679b831a4580fc47dc957bdccbd215ff53ffce8324caec7f7e1ee4809c428b3c8f522986226f3414709f85e19e30a719e31c6ae09e25b334c83f8d2fcdae18652ac97714ff2553fe3b2c8577d4ccb1fea7bb83eae8ca987628a59ee214688f3ecfa47417c679e715d3f2ea016e979b8ae2b5ed7f5735d4057f48b5e46a8c3cbae9f262fbc239e8acb5c3f6d831ebb88b4482fe3ba80e88b7e871dc8187a2b063b3fbac44a5b9b7233ddd7ceb5612e3c4e71ef9431f538bcb9ff5c2dae168bc5b55a71a9a4a8522e94cbe53a59178a29043f975772b93a978b73b95cae4dab2eea72f574b9e4044cf8f56af51206e6caac7d20069e2da9c9853f0f7367ae0dd33eefba52c6605c7fc797a44cff72c70bc9f430ee788fb2346ab9a374d2ba6317b1eed8b1dc511aadee289dacdcb18b545c3f63a7ba634b51a64fb592323dea8e308632fde9fad0ece882f9c9f4a63b1e2953a45cdac9d46874cd6c1e5d3f2fe39794a9384366879e2c5d3ab4a4d35354aa33351dda758a395b87ab53b40e9da2757ae3e89c824e4ea7a7a83ad3b581c9861aa0ccae5aad9b4cddb419bac3dd8876b13bfd8c866d33265e5955ed91f34b346c92a068369b8140269380a00b27b9192004e7511a25694159a04109799c42e49448340c0ed98241be22b1a38c0c8d95e4ab693a19d3b3f1122d7ac1ce8f92c90f113e09d375d6ae561765626291ef362d7b966b13999372b3e2eeee6018ac8c75e28c8e7def20e0059b48bffa1d8df50c9770b8e1fee931d82ae6de3a3beba059d3f04998110c4a811de5e947f0a7a70ffe543c0ff61c017bb8e89c74ecc92ccf712be2c9f35b518f153e43f2fc2192a78fba1551a02324a38cb9984b66ee4bad68b3a2631d6ea46d489edb15796e58cc0d491e299044a2310a445ff39d5d5d1c45a051665e360582826df98412162d4eac1539c1525c12c2a5a016e73c88c4ca8fa52030886bae053266bb56951d8771114d8bd92ccb24566092474bf44551fe66c8e325776865eec016e7673716b66fc2d0cbae93dd3bf9ea2e2fc3ce3933f23c27b698b97b34580e97b652777bd09fc1c2dcae6425fa244c11ad61929b8155b266db46972c4f3fa680f29a9cf48e33b2c87d8e33f7a09f2b4bcf60477bdaa297b2daaf6ed1d74cb11483fd7f46d1d21af4cd930169fab4102d03135986272b7128f75b6680e006ce0b003baee65117b9df22eb15fa9377669944c53ed81d23d4045e964ec881908ced6ca7e2b2eddf768dd4cb1ef594c3a82d6cbdccdaa50c6667a83d22b79a3f97f27eb5e30d93f6a3c55fadac165b13f9e9594622d4b079ab508b4135a812c93ad47528632184ab100ad7a01a5485647c86748105319c808b37c8fa6135f2d344c25bafa846648c0f1d609eff1a3c0d797899482e8ddfbc9f06a2dcfa5389dc0aa480f0a9d72b648d115933719194f72d15ecd80d34b7a8a20867b94515469ff38edd7c13016ad8c41d1640ca523e6f03f54fff8c15f59e32d495d96a612b10911f14aac39bd3bf1aee985f50dcda2133c5530845994ca8dbd0d3ad3f2da264f3871269b16faa91ce33bca946644c2b1126113e8583cc3304c9526fc916bb53c2f7fd80293a6b03d1fc993fd306d4246f3ac77128140a859a57de7166f993bc28bf3d617975f2a419c5741bcaddeda6fb435fa5aec3d3a700a5dbd0ef8e3368cc29e1c9d3e224d2f58a8963e6a6f3675a41e40ad9e22c8fab223baee46c2b3a56fb8a2799f5337fa82db275e8491ee90f913a942b12ead5953254958a095f2e71560bcbbd748382b74b4f412da93aa148ddc5ccdbb6e1d944e5db57f08fce2bdfb016ea981965a57acac7965f2cc36a5d86e2c6630e88572bdcfaf6158df557ab6b6761ef07cdab834fb9a824568573c0cc62b91795c4b6e01f34b3580eaafc7e863b7a985e330bf760613d65e52998854262efca2f1ea7102dd315eeb172164ba585479d15dcc3742dd3f0082d9b50aecbb75b72d94c948239aa6cc2806ac571263c06c9a66f97e2945985c9445997a1e9364d5554bebd542a95bea98c477cb9a452ba94dad0121e752865dd745d582f7df2cc2a58a756e492c934ab983f6c95d26f989aeefc32b5e922de5bf71fcb5db1bcf1572ecab772513cd7f1677883825d57de157db5e95bb95d8b2cc7a7d7744730b3ac2ec31d2b94e3eb3abd2c97e1b8caa5b35cd065b51d2c95beed6a269615c5a794d2bcf2120a2db1ac545454f0984351e8b5a1a631478582d3339f36999916534ed372eeceec724e75c9facb291e615c657ae9335ded7277e14e79acac1ce58e391905b74ca767f9d6327df5920a8aca479b935b26cc825778ccc9a5974e8f32aa1cf56f03e9c559395539bd9b098f392a959b465546d95054b0e9f4a6d36f2a07595f61bd744793e9db4fa6bb3280995963e92b384775ba0c8f601d05f7607d05f7b82fe5a84613ce516516deaef6d23bc4b9f8ad97f0f8822b0c97b73e43235cceb9b870dbc6954c5ce9dba90b1ea5d8408edb7035e1b17519deb4a86ecb55b7d582c799b994d357dcfac75d9a2bc3a568f4a6bc8637292c4b4d5ffdfbe6dd2e7bb41b1e5599aedc945734e66da62eaf5667c1a35dadbec2638e2aa71c3cc52957495141b93285aa9ca2dc519551ce62b3b76d2b07cff262b1a12b77ccc92b47b92b7a15ed2af42a39dba6f2942b738fd255fec990089d1cd414ac2a53d3ca539d6597c725728e2aab7ccc51657ab024b3ca4dc9aa51880c1e75c79c0c5e86c6aaecdbc29b139ed69e6ecd1617f1bc94ac5dd9dbc71f990669703b9dc0d28f323b66b4d054258a09c584ebf3763b873ce6cc32332078b063df41f0b6f4abc30dafe8abb4e1daa2cc1c8f6eab2a0b034bb11c5299a275ba0a9385ed12469bdf76778c945eabf6ed72dcc4a3fc7cf771be846568e45be2cf558b543b77ebe78e4cdbe899c50c8d766595b8b34db0e3aae5ab2c2343079fdc9f59b5e4d082b65c889599d15ed0659994a37892fb41ba96edb4ec18d1368ee3c028666d23290a3a670d939907b625eb6acef1f3dda498eec0ca707ef6b0e0930debefe89e924e2f7f14ecaf82f4d3c01aead0ce691cb869f9eb40aea3f9f3c0d2f7811e087ea10eed9f895e6a9dd44a80520ada7eb6ef5402cb8215c8983e55818ce93bb19f3e2ad0fcf67337a0b911995ea6566c400d9bdb4fc3eaa7c4b427cf6cd3fdc48e5de6a131fa06fae968cfe6b3d1ed6723b2614181b2153e3db545fabebc138f12a967fbe9c9544631c733763fa0aca5a02c5d55bbc2b763649bd78aea6bd63e6adf5ab56a9886fbdb3ba924f7ab95815d330d79d02fbef8e28bd59469b2e647e71900abda26ee866ca8053bdadc29f8a64caa545ed8715e665bd430ed3079231b85447ae248eeff68189d4b54a7549e1e2c6232da4ed5814d89b6ae89269ea03194839f652967cf16aac8fdc9337fe8777226f964e963dfe2517bd4fba89d4bb8ce9660b730630a9995da63427f16f5cefc011795763e26e4b1ce7676260e4d0ef2879e479b1024cd0b2abadb4d709f33e45a560a403988a768293165e0a70cc43ca00ce53c55b6039e8a4e667a77a76c864954190aa642042832f02d930d2b99ee94407c3219de20019670e9e0951288cf2bd5d9d7032b5bd49e6c331d5aa6584bd2925a26c32274a0905f648e6edd048d51d9658bfdad3303553d4795bbb717b6bb0ded7254b5d4e5b4d81a289d18e5f4abf47921879f48cafd26680cbc875148ac3cca29952c92efa34cfa3850863b3a3c729e57da9a28009581b81ed1d708ea2c370d79744de434ac7be7f6680eedc95da9c32d1edcbb77d809da936b8bb2d650764f9db5b8c3f578ad3d01b2024808932294299330e33694dba7ade8216d458b724a9e9cf6c2ce1c151542775053b01fe96cde95dd99465ec8128f323d457cf2b8f914e9d9808094206182954874c02423c9819329dbb62b62603bfa8281f5f1c3e64d0632a6bfc140fed0b33cd2195092dc3077bf6ddb28c7755dd3f0a6446bb8434a29a594524a49b1b85b508b2de484a08f5e9ab7210d6bbafd74441a06a378654b52d23967e7ee708714c7d934444dc1d2d71d34dc41e56c5a4df452c6484c71dde9212f74d156ecb4b84d3c768f1166bea53cb0dde90eec276de5a4941203b4274fdc437efb2737293fe76bb8f9c8987e3ff9c9b4f41901a8ac842f91bac6afb3c722d9819271f3e98a640748e6dc7c3eda130429cffbd8ae81993becc3878ecedd7568b9bb0e307759d67357276f39b4276bcd837bd662770f8d5110c857bf043e40b97b684ccada2777d3d9f6336fe260c7d9e384b256e36af6e47e922744e82cd6326a459eb6c88eb347d54367cf0cd39dd38e1d57abd8fbb661ada93a85c00ead8c7c12a688243c69d8bcdc82c827cb2db4709267b2dce20970c832c4d9f2c450cc2fb20c6bd35f7721731149f0425096b9882438695811497092258c9c33f876a8b88cbe7e88b6d1a71789b6d10fc560fbb89fece43e1292c88b2730ea4593dcb28e431ee5923e85c0f6dc8114e8bfceaec6836036f4d3c3b31302999487b134a65d7a186c9152dae1390319433fcea019d4b0790e6f57d522b51f911683ec9c787646ec38e70f8df5e9a7d0250c9d5a7ff13d61e7658a1d32c3114c965bc825c0c2ec0a4816a64da0e5c85019191919191dc8682ddb06159ff3b3aaa1cb91c9b46a9acd91c9f5393258bc3bbce9be6d631479cc91c91890c9d30999314746ce5bea7ad4d3ae619f4cfeb8e12a694cf56e9c91b58f30596b093f8219f5f1c391fa58ca9aa6c259c3e376ef07d497e7cbde79946bbaf24e10cfcd93d53af16d9a08349a337b32f731e763ceece138dc637b5fd3364d2b72f322154f317b64462ca56d84c950e7e0c3809d971f8a8419e98ccb9ad67d9206b67ebeced98c6a94f3cef24ada7f70b9fa987386754a9376a19ef66b1d7fd44cdfe51f95cada36e8398db2f00252923020512a7c92c6a44c4a99862c47d9852cb9582d9139b8abe4374a36642d0599962e41ac8131401c91690cf9d26a8c0132bd56a71435ed0331da946d53cc4ad9f04918b0c57ead44bafa97572bf05b496ab1a2b10944674c1cf3c8fca1df334a5fc8e304439e444aa611506e26413748cc2136d87155647ed532f1ce7c5f29ab7766eece3c81b4f7e791efe314caddafb7ca4e8adab70b4a51bbe30372e9ed5d23db6d1a366e2ff5d80ebe4b750e11de6cb86221c2325893b411a2611e2ee1eeceb4d84dc56dd7696f98863b6f971bee409ab51e6387226b94dc5da16d9aa6695f05c31b6eceae539bdab4b2bbe251764cb0a56fb5ebe8101cd781a82494a3aa3e0d79d4832d6e98bb30da2b77d2346dd3346ddbb6a10dc9a6b2da666f3e94493ea261a04c2817d48852ea246f47ad8f73ced9dd734e38e4cda5c50586855916d631eb1b8bf58df512eb1debb4b2824ad279e57905c64f7774fdf4d41d5357b58b4bbd4bf518d6f55378837f42a9eecc2e1776c550a5c488c1dc856f8c7f3485a650538cd3a7e3f4efa6ab5ebe7d3a497ad2b3de699e0f054afb3a2abc118f0a6f5eff522ad74b7ca5a8f476bb068bdabebd1e61e29051832a169beb1bfe76b7d7266e3b6ca74ee6b7d32e96e44d5bb1c09aa08a206fd48bbcd138e4ed72a47050a12ad4e47ac350812a3c9e2ee3accb70878cf757563aaec543c65967c9c03d5e54431a16e3dbe90f8dc11c0506ebdbca37976f2ddfb6bf2e152f55b2fd4bb95c3264b40ea466179716171797d373adcda5c586b678b8ee721717eef1a2fa54a03d2a152386eb54468c43819263602963c618ff35577884ea3130909965e0919ec29b8c0a7758dce3f4ef3d5efe6366d5bf145005bcb2e674d4e94e33c8982dc6a5309762d1afedae4bf1a577b37d67172d6eff9d482d6e57dde964264dd6ed59bbdce669717bcb6d212d6e6fddee6971bb0ce7918cd9be72d655ce224571c5361e3b8e09b67be52aef7fdacaca0aeae0ea16d1e2f6958b448b1beadb26d2d736448bdb28e66d1e35ac8bed1349d6a8be7db241d6a47cfba7ba33a7a452ef41c2c0f3206bb08cd94a5d989219e56e37ddb185f8e0c04ba5d8aff72e14dc17b8dfdf5e56796b94ad0ec1a02d257c12464a393550da225a78a3e12aa5d6b508da6fce1c99dc17033259c33dfaa67ff39aded7f44f861b1e91c89b8c4c6e6d893ce993c813fcbc5fc974c71976ff36f0d63cc3eeab5d88f3accd0de4c21b8d9ba1864bb3549ad566939707cd1ded66e4da188686371453dca23635ad9aa48c690cd362fdad1a6cfd101bb6f96873adb7aa3c761884811dfffa318734cab2a8d4a4b9682e506a1b0a2075e674f5dcbecd256de9cb0ada671e7779f96e0aadd434e6d16e933667173e0933d2924c931d7df9d83969d19c23f8bc6cb16df2e51cf4ec8e7ecdf2c650ff550decb4cb976452524dab94d6ee2d7ca5d9b5c7e589a78ca99be6d12c5f6b684bb1fbb365cda469f84ab2a63f2fdfc91aeef2dfc42519a3693c3a73b893319a562beddb39e89330e30e3d998633f0c815e5c90de55991d027d8f0a2b85d66e488b246734ea86130d7ce1d69588c6b58e67045b95e6c9186c1d68fe20c19a14c4393e9b72d9c58a645faf03ec18eddacc6e93b10743b1d4f27a46334a7eface87c68f7436335a7ef8072702738fd7744632de4f41f128db509fedd53d2b0049cde2b6ad8034e1d707a8f49c31670ca80834b9cbe3b6a18024edf75d130254edf05d118ecf4dd108dcd9cbe2ba2b11def846c7cec88b28e8f1d934cc37f5f8e3be5701c77cee135777af11b773e79ec4e3a1c767b761d777ef11db743701b77d6e133b741f004dcaee20fb85d823be036cf17709b0467c06d2abec46d111c01b777aec4ed11bcc66dc9343a14dcc78f55ee9effb039054711ca230b2a295356500a9314a316e953868668fd368b067b51729fe0ba7ce88bbee5c67d21a22f171717214cb890001d569edb76723331314d9a139857fc821d65515f1c678c32323436c14e6567917c95aff9d9cd21af8b4fc2eca44659cecb44132db6346a823231019bfe86c6ae4392fb20132d73d257668aadc84226683b69346911ed60c7344c97f4abcfa46774cb31d8792fd8799a696c02fdea7741e4e409135d90a2c4931ad1e6c2f04cc34ed1e44bbe71a5736a5593dad874c3135719b34dfa854fce58fa22dc8e11d4e98b72dd36f0a8bb15cd3927ea7d572c36c4230a859a2f9ab50ed6a2ce15856f944b69f11886972b0ac35bd4c3cb152969118542d5990a0b8ffac81185a716a0ce11b5c815a176a0305744b71d8ea86d7451db688e68888611714a38d40ccadb5575b7693a5891b7cfa03a7491c56fff6228d3c892a80e4ff24cae97b20675f364c9b396644c3b9a33b7301e7368509ea7fb2d34627e43c138c41c11ea1f0a854ba8221473a18ece286c43eb55dd9b577d0b6f3ad56d95f09cd8b5c3b90be3f2108f337218a4d11e8dfafc681488082909a88b809a099011d0514fe7637f564041da91d06c2222a4a419d17654c4c4681e05754276888768059427d004e280e8ab076936c97394475fb252622512a11c8759b55855070acd704673fe6b5d99b59f1fed4723d28068ac8dda08a88d8038226b477123a2313a9b11cd8856dbd14fd7594b8de8ab6bd759db59eb097946ff6a656d9050d759bb5a7d2a6b8b3a4ef5510b8f10bfb5b8b75e84b8b98e995f7076dc7bebb6700ee39e8e168d7d3c7dcfc828c828c828c888098d7942f4d5ef3aeb0955269e903676b2a1ac1175a345c9f19a8fbf714bf35186268f1cd14f7f8bc13eda999f9fa1a1fea1b13e35a2318e870332323252e91f95fe51d9717b0cf11dc7b93c60dce381d3e2817574e67122ce3569d84f66c97dee8843a2b19dada70e46c87d2e897bd2b19d8de80917b9dfed74ece396344c12d5c127f7392694071138a73e9d2eb8e38ea9eff810f78995c7388cdbe38995cbf80f56c1a27efad8716f7dfcb8301a51df81e79216576eb960b7fe66e3eafbcc135272a2e396924a37d713e27a3b402929170050ca654029cf4434d6d78e6c880240c4720060a220f0d8e5c0a3c581c7550d1e7f038f228d7644b3016d44db11eba6c7f0b882e1d19a6e0368068fab1a78b44d03b30e04eb32473f6c471c11a784a7cf01d1fb80c7957d0c1eed0c9edc28ef8103e281037ae1162e21b5d85db4d81a1288c48eda91d72deec2640f7fde978ec49e2c8f7880e651f3a8683bc05cc66df1f8fcb1cc316e8b47aac7443d75e90273fcafb4723b25b344836446604018ecba395aece34bd32247d4d2e26ae48c885adc6b8bfba494333223df0ccfc86b52e76790aa081b3c23cf085cc2c444233392f2f930a9c30fa784e3227b432c76669c91670c97943cc33c6b5a509526b3b05c6fc813b28265f9e8097947b423faeaafac76f49247aee5ceac1d7d35da957667b4d8445f832e2d57e6ed094cb2f44296499c7094670856c1a65e3f8a9c120ea9458e88c88ef52b1f3d8e4807ea74ebe17188ec1dac460d1b65504e2cb99e3822faaab5f50abee2316726d757262015ecf6313cea1bae46449d92e74b2e79fe8b91e74f31791e25bc5547e7569ea6a32e57c47146dc11b786dc07736832cb6b78c372d3f584bc237986207847d43f943bb6e667b2cc2847dd1da5a31cbcad8975948e12dad687fabc278c1a670d3f6f4353deba0dfdaecc5666d6ad99a5870a7ece4c78c79c19b90ad5204fc81b52a56eabf499e7a54cfb27ade5946ca88aaaf6dbe91673451c51d2e81915a137dd223c5c34355526d528c4da112706cb319973db34f06a4762d08e3622fa798a06cb59c1725c51c3240706ebdd19992fb68d68dbe669148ae82138228e496bb8e29133cacd1135c59323ca34029862ea34a7802fdca60e3b323312c9a6f57ce0f4645ad4344dd3ba7f325daa33986606cc75cecbb45865e68fce738e60de26debe99c5bf374fc3bc7b78bea7d4baeb9e39e969921d572a2b53f1288964647ab827e26a45872e72bf05466b61a2dbb66dc3f2999ed2db49ba4d8adfe24a26065a2ca940354863a2c59652bb9c408bcd8016b72b5a6c29e5cd51c93e691f27516bac3e5a0bebe8dcd23e89a612d4d1447ad2ef9d8ec92c8a9600b5585af5a93f75088c07adacdb41494f8e9a28293a22247f5a9c425a94dda6168b263d611d3561e516962d6fa199226ad2a276593e89a8900637497902c0c2b4a8454a8534dc5dc17e1f3b96eba3de910ad126b95be868a448234d1aeb6cac3cf33b5d929b2ac94d91b4117df5116a85f61797d648afc83488623189fad5a73cfdeabbf0f8d5c5e3cabe855aa8b330f0685d5a8c5a2c3c3e37e923a396e93287ff5893657e734a3cb7d902c11666b1ac40fb43dbeee929d24aa909e53e156282911356c0452632d21e0a341bc1916f68c88b2ee4911ec94db1c85d93a0c1e866c5fa597766d6c72ee36318addfbbb66bdfa6697f61bd85f599c22df0f32c97dfb5168859f0c8041359a3bf8a4c7d829f178a6720acac019d0c4a0962d414ecb7a7ee08deb69e6a5dbb23fd8651492cbd7cca3f6e86039879fbd781db4db56ed35a0affd0f2f6f994cbf088d637dca3f514eef1724dc3b5457c89ed5da7172c5bc4d760fce2da220c3cbab026eb9b218e949335298b75977f1bc8ba9d8d90b8523cbafc07cdace3df05a759f778ac78fc41cfb03a1dfc37b7d4ea9f9496058ff3ca399f53d7ee942ddf29cff716dcc263c782ed27de708fd5c11506e9954694342d75c7e7147dc9f205060c17979696568bc5626159ad56565454525254aa540a853a9dac45413199c21004bfcff34a5996f26cb530cb5998f591ab81f1978f5a9e2d2f78dcb2bccb615c29635cf0b8e579d6cdf3b205b3625897e5128ff4f6f32c574a71e23175fb436322a7fe75c8e3741094f2abe076411912c1449ed7a68ebc1a535f39b5c9a37d0affd03278abad56b7a1ab7bfa8abdca1d99c8f6d3aa74a85497780b7152f2e9b2b31d37ca5b5cf3b5a72728683ee1a36e118ebb5389d561226b134b504a5b344ea21692293cae700b496b1f86e18d7d7844b345734e395b3ca89635dc4754b6853e5c849b9f18c68ed527fb6854b0631bdd961651aecc6d945b5a9e18a68d72ff79a4464d7c86d690351e23f2a62bce10877a785a221165896568c41341ec0c61279c004fdfc2c941ec0ce5a9a48d1a3631e5e9bbec0cb5cb5b84fbbc40666e25710e4fc19dfbd19947103b431916c4ce5096b8c82c889d21d9141c36226f447b1b9133d390073d885b336f78dc21f313a7f9f3c0ef88ed043f595ec60c5f64898bcc8c38213f3f45103b4332234e485cc47b915612ddb97738c894b594e85e7a094b517ad75dca94e0ee799f320f0731e244103b4379dec80e999f08626708b778c88c4cccedc0966e4802db9291d1c86897a7d7668825d891f2501fda78470ed5214b5cc31d3363db5834acdee3bacedad54ace3b898ab2b0752ae1296a1b3d8926515158a96acac1ca6fff9a7b73942ec100c9641231e1b34493dc67008f103aa4c99ced85d5244da2c54994298f64c2935b16310089248258a6a83a1a0d40155c2b09ede1431ca45ebb8eaca544187ea3f2627777c82cca989631b3030ff3b58030b825cfaf1ad671b7a52eacf71e2beedad6999566e15bcd766a52dbd0666da37f2a819d539b35b8dd1dab9a497568628a9f24c957fc23f1112c721fcc335a935a9cd1f7a01807e52b93f25893469d5c9fc8fc9d8c7042828ce99aa4ea3a6b57ab200d574c7117a72327f9242463aab6cd4cb3ca752522a0a4cc9225134460949534c92c596e9124287f21387b3a207442903161830085052b45d58bef03bf2fbc513997fb2724c89a94f73f13282dbd49054975d2625fe5366db579129a294f79277556a65252a652d22eb141a9cb9e9e86a550ef4bc992f5535096e5e5b10be2a1af4ea552d2089099e5d160868cca283c6a57c8d0879450fc8082cba8cf0dd08cc2a33c145ccaa5f240682ee1994f5ae733249f844e479035359f841a6687cc4030714deab068710cb6130a6a6253789451c8f3f43b462a564152496a1bd8d1f2a80c81f4aa0cb5d80d998120ab10b5d8a7c28e2a43d90ac97d2fe4412f5f0a7128c69647ca24296bd2462463320a92dc3c764441626b52f5a20baa5fd4a46ea85bd229e996744abaa26e49d53a236d874e0ba9f046c3d3ee906b52c34c158ba1094b114ccaaba3699467357243aa6b826ac2165bb08ac0a1266c9185a02624394aa54860471425444882da0cb98520c53e11e5d3514d2a82e4ba208d87be8c725f1b125bf9b1a2456d488be6a30d5141a2b1e74681a5af59d871e54705a96114cbd7ab01fdac10e9588bac6d3085273322af6ac91d50ee7738f1d83109f13c02b1fc903adb3326e4d6a1b8bbdc0eec97a29352d943563f593cb122a43d593cd90138cb620e469a15727e2af064048943059e90206b80d89311240e4ca9b0230a5692bb0b77a010514dd3b49e9aa6699a0c4da34e46196ab1ef43632a25fdea7fb4dac72b69991922cca8226a30079552542ab3e77444f4ded3d373121a4f422d9e08b3cd485d28660642b30c6b521192919191919191514a504a492528a5b3a514d52cf75566e30a8fcf5276324ac12a8cd2b2d542c2bbcc05d0916dd711a2311d594794bbe8bb8eccf3be7d7edbfee120ad79717b90efe00b20650fb2c2d7919d86befa3ab2897d24013eec87384837ae349994851fbbd9925f82be5a621f496cf75e00294302071902ebc8be5d4786a2824d021b71a2488b87cc8826eba1d94c369166b3dc43b359f6f0ec6b49dc5200f8edf328e0371c64cac09bae231b251101a4ecc32d25bc961253b67dcab67bad397d68ac35718b00df57ae04ca3d2c857794af60298c24e11d65e552a0fcc3dfa56caedc27ee1636cc5d965b906005579b517a022b730b891dd3c1f0ab23b1b3e31de53bdf575af3abebc8c21b869f0f5738c80ad6be0741c1423ab2efbbde6dcd87d79105f1b0f7ef4978ff3eff7d0f71102d888775643ab26f82de95b2af265121b6fb0e59ba0945082588be568aba69e58aae1479e23ce1d08257a2823dac019d84a60a248e6d264f406c9e9fafd60a567bf70d35cb2a221a5bf9a1af7ed759bb5a5d45f4d30975430dab4a1ac604c9aa7e13acb20a76ac49b5c12cdf4222d32aecf4993d2dd2125814a0165590acca4a050985945b4a78527cf72e65de952204dec10701714b0929c07f97b220de411312121e46f1099140e931d29ab3b9a3f148392fad9432353434a4d2a3d2a3d263d4a9d81495516e49633a32593353ba55caa9c78e2721a294a00e8b14fe8ec2a3f8f0278b828f641396f435f1b842921b4bfa9278bc12505c921b7301521fcb9deed8d9a30289a3ca41fec0025953bd781215811d4d482a2255118de9c8faded591a998a89064cd4a45a452014a0f7db5aabbaa9e10580e8f282a9edc67a192d826ca6377a4ab837da27d43e108ec58936696425ae4e159d524531135998ac0a0bcfd24445fdd5926dfd049e82484c7ae04abf9f11b4aaa496317f40de5a186c924745092fb1f9286d14fc9d6539f68b39ab44d252df635a38ea70452762ac80d031be4fe4cca26a46dec824e42251ffa3221553c7613cb1251ee775874425d50c987befa79628a34d405814023b023fd8666374ce2a96435db36068ca1ad84e98e72ba7cc350f8a88ff216af5a6c1ce30adb376c9c5fb5d88d6ff128add5b1765a8b4d2614eaf255cc1fe451f451e4496d931675a0e0e851d7342fca4f973bbdddea1daeb3a874ab1506ba9e854acd8c000000004314002028140e088582e1784422281ae77e14000c93b25872501b674990520821630c2106000000008c00a0010000a0f86be9ea235ae4fca26828d9af3de15226a12d575a4b24d945c8338ba71ba401eca12d29f2eca52907b9bd56ac34b132ecbcc7efe3f90b964a90e5b17158a631ebe7d8798472d66f6fd3bd50d9b87950aa5f3033eb578357dd586ace7f574a263e480b00bd5532765a319bc4dd0c5fd4bffd11036ec55380ecc7e3dd432f61fc72be4d7e39065e47464290755ad4c1d44f465af534a75cc750b9d2575b919c5c8fa6dc56d23baed211509bae52cdfc70f41a15cdaba023a6c22e71e53564543c3af2516326c437b1d1db835f2e9445ece61f86f4037184ab04a05715a0aefa8637c95146a2d0ef4bf4795751fc161255fdf834713e589bd04a2ba70b10deb2560068e523dbe552f82a48ebfe19928fdc3d6bb0673441c7773c48b2259f00f5081174995594ddc23ac7e13a0c8bc9b25de31cfcfa9fbf7ff035de97cf5b632f3b281f26d5af9bd1ca0d1c141f92ce75bbef8f8f780fdc88605051190c37ab8f19c228ec782394e5f7fa25f662573aa16a89503499ef2bc42dd301c0406a31304717c6a0b2011e7c450ea24c28241cd50da514023279fafd3afe122aba0de280be1c582eeb920498004f8fd04cbea2c55da75bb798b17754228379f5fe52fe050a55f3c36e6043be62b906141113c494cee8931d0de8406b07ec5f4bb3889a363773fe549b010a038100db5ef97fe349009fd100e4294445fb07ab53a692d969c1a35d8e5f71b523857ea09f5c3f76d952515d8254af2708bdd3eb56e019129281a7908d4d9610c79868421ec7aafd6994b27f97deebc82627866e527df26b3508e3bad400bf2d45725224506e6df6ee6875387d86df9daf248da3a0f8fa66c47b46bcdb6ac7f6dfc8707680b82b9511907d8dab3de72219d4d61a2c6bf3425fa0f3cc149ea4e65d12f0f9edbae3bd695f17a77b6d95fe01d830e1df19b28779e21777f79083d732d66278e179dce79beeefc1c386e8d5db66e63f18c8ae1a0faaa0be1ede213bbebc8a3045eadace142aa00db927b034ba9d61cfe217a38f3fda6e3d316fa6344cee18079608878ddf896a91036678f1faf7fc8cd52748c1098bcf59b531aed63d446726adb3933e730bcdf5e33dbe5108c1bd024d5240f7d59f7a35729db322d0db4802d509929a0d4d2ef1c4dc9ab9afd76c902f66961445ac5a0b75c04e6ddca551a7121b7cbda6b0be2418feeb8b6f26e0bd0f06161d5dbc90891553590ba7a170ea3f57e07e496a55a819a5ab5303d91d8deb5d7018e0af98efd4b44ad348c95364182b9b97d286c011593e6bcb73f3496ad602634c8046c9e8b4e8a6df7e132d6e2775fede1944419d5f2621d01b215f8983c2869afe2d1ed238c0a716432d4371bd5afae0c168bc9a2f9206d2fc3db2f42e62fbea232a35473b03092de013c76fb89382a1911d99c122e14be8ab493702971061b335b56314eb7dfa21ec635d02d26845766d809acae12a01bdc09d487b989588ff8444c0862d663f6be8f914944745291452e12048d3dbfb7188d3b4e84919e344af46e07d2bc6411acae818a3848e0ea78b836b4b93047dc278aa0503b34fcc1dcccb39b1e1ccd72db0ff5b6fbbc3a1428fe88503be6f120e3da19fd2f2047b65aef92bce4a88960df96a9e46bcad3f783119122372685434ef3cd64948e48220336f0079e8d8e4c94a4b5b790ede1ae338d1f811a1d8870de41b487e72963f903490cb6f52beea9c8b7be65ce66501152b1572218662930f9cae8acd27366ad4fabc7a8682e57a9368eabe13955435855bd2a3c32935a56024109d2fb4da5be3766cbfd02f1df2ec75037167ac71e4cc45ce1a742931205927562381371dadbe59fc2debc35e56c8cb00c06e18bd4d98aad0b8e7aedbd529743089b4f797986cba93d91095d42772c1e391c68ff3470d8192b0da66566e2cb8c46b482db686ef0152c3e148702e04805b12424674f43f1c3f8295da26a8f9a0973944ef1de4a7b7b9791fb6ac167562134af7b9577ff91fe8a3aee20111343b591479a74434c30c6c3a1a1c2f1418e7d861ded2d100a04f6776f19f9be46ba3f63bded05eb9dd798aaef0e308e486e53b67b6ac658315df4c08968fc989fe0338d7661354325920935977f62dfb342668b055e76b3603ef3d34d41eddd82434912e535fb11b55fba9dd0404ed0175ee28bb46c2793e55f4d2068b7a98db7213cf2b67e8ca1e789b811399cd04923e79b24dc576f2a4c1edfa83cd9cfb7629d3dcab9af942d52c15e355398d7b3bb15469152f7387f4f86f41bb63e6f6e840d0e831f8aa71a9b49e38503e7435902bdb386773e2045660208df4480eb38b5f1dfbe7227830b2fffe9bfc2b009c3aae029c2924e7f63934eb5d67153c0a6af33735238dcffb9bcccffd9baa330df465384f57eca810ce65a0a1fc119c43d34e9cc703c88ca1293cb31db2c7feae48575c0320cbdf9313d5662c329e730e0c719b207c13efe90ef7f14fbe9c1368cf03cbd808a79d7ecea35755c06fd06577504e789767e50b59879db87aef5ce7a212200b847f372317757cd9d13fca391e8febeb4c701900f9a3e2d400dde98a5abc73ac2c401d2fb1314f8166eea5f1c3b483d73a0fbe7a7deb09d18c2cd01c43db38e9a3f66d67f45980d4addd2bc99c5c8cb74d73bbf841052dee7cbff07aca836b4638c2b25351a0df60c44120dded7c743a9850b3c66b06f36b04c86243b5980e202692d006c3789046b063d18d94943ff4279cb360a74127a55ea164ce4cf707d1c5cd9c90f1256de095a7726b439433ff29655cd580f98b27943ce474532bb17f3cfa38761095caa915c2420d29e3ed8f772d2e69ba6826bdfcbf30d68ee09cfa7bd8336f8ae152980802cc608ee6417e155be2921746022214fdadc235a26bae967d1a3ceb7b4329050047914f6f26c5ae8941cc89f99fe19e5301b8415d1afd8671351da080587bc71d432f2f70ba27c2dfbf92895bd57aa21335dcc40eac4dcbe41c85800e68173fd23af3fa7b6583076c880e21403e662be5f94e34a93664da6ed25665273b38cf8336ddc4b92c6d1b056b5135f43b8349ed25aabdee2698c74a6bb4308e2ab9f9a0c1a9f0a7047c2870e0c3d70a450a716e727220d069b4c6131b6a3c2eee132ece2bcb88335b7d45a11abf0d276e350cb8dab24e13afb6fd3fd95d8a2b423154b16eddc07c264fa2447aedf91bec3fc67ba7ab3f47694433cf28af86cc565477f3ca7c44f8e473ad70d00f7d5c6e4c5b0faadd867cb1f843eb11e378984091667545e23951d158853b70e442c12bdc32971b1bf69262120cc8ea92f39be50421210d8864845361896db7313ee39e9f20f42ba86fb945908465460c405564ee3073a7b4ba21cc83371a6430193e23d7761531c35b77a28ca0766d55e5b131db75d154c551d3d4d0e36cc35072bab9143c2aa99a29e224e1e2ef0036c657e3a307e73e3fca26813e1356f87b46646965cacc3b7cdb481b0aab1fd1ec6037f8124336f6d3d7b9cb7c082427506178db0232554def6ed03d93871b06423fb003cc9b11e42afea76f352da92551979dff03381985d6fbb1081a75e6be020c6f5d59ca8f9dcec666733c7133fc18b655e7213d61080cf542c8368fc72fbcedf4a1301614f4c475acdfa672b27c594c9e72a369f2f09be2ebe2b23ed13c43a0c58d3c172443d984a5791158de6915314fff176611065f9935e8325f808d911a605d6fe168d85d843f76888f5f475e09279c5c568436971e2e9cba947c61cd680ee3e3ed191e4b3b179eb2027099e11acc4d4345d47fb1ad91b3f2ebe911950f9e3c52ce603fde077e163e1123df519be6e2f7d6a7b1da7caa66298f73bbb2931ecb5775414a749196c2b0182aeb4c36788125d84ee52c7be8c85879a5b36190fb471331eceb9fc409fbe14783e5a69f2fadbb6e328d3dd2ded9cd9372fc68242aa3857d59c6ccccd6d45a4812cf2c3bb416d91785a2682546f9e2f8d54862d91e9ade206680f20850981661500bec924367037d64a476f2f382d0f9916532920a4132512d36402363acf8e2953a316ef4bbaa40257a54dddaff052f12afd1511d8b416cdd94fe0f34b9810c932c941cfcbfb70ba0cfeeb74dc0aa1e416dc16f1ebded2f2b5509894e851c666b17376abd0b6f8febc4b1360575708218353b0545bbe9b480be27a51e2ed2be1f287964a92b0e8abf5638edfc5b43b96c7611ad08159ad4f3a05e70116bc281cf8701825f80332d7b3cbb22e43edf7f85af7783d6283430db1ff418d976e87a48d90479fe404b219b1b3827acb67f3f1eda025f764804de4ea7f8966943b5911825be7be3e7396205e9114029449530cb6e68ffbf9ae9307c474bc27915b456505ed4afc650f39bb693fcee38ede9a813ec74d1af06109867ed96bf19ed83a65a37e9e84bdbe3178c8902144ba60868f8d72d1e4bca79205fa5e6248034f8d820c546d5e944475c2ce60ea861f93e8f04747c2c6c8cb00b9c349154e104a52bc163e664b098c5c1240849e62192f421893617349748b2b9b193a74892dd194b62cc6b2d83199d39958f60f62ad908d272784272bd0edcc0000566f5f8b39cd9e076eecf0403a1fb98eadef33306fd7d5113671c26eddec5ac764e4f2c470b21da753c42d5e2b569fd7df0e7dbbb3243e09f9a1769ba5f0e5ed50234f16774cac4217eac2d792c317dc48b2bb1fa0f9e88249d722eb6ee6d2c03b865e775bcbbee7b9fad346ee71cf98ac3c12413bbe64fb31d3984c57fa173b38526d4fba7dba6f0037843f630a8c32e819a3e3a45a8a58a04088a68e0a52897c3068c93d6dd2330e08b760700472fc170510016712a41c17873137c4342f2dad36ac4c16f5905cf895a45d7a6d7e88aa8389f19cfb1b6abf6bdc15c2f2b5e5d1eceb21120bc15b3c6bf107fb8becd88b1de76cc9992e81d869ae19d7a927d8c2def3ddc2ede89ce80688856a5536c650a555b5c4e7397db26a3f2f03b61ce0ab1be7ae840df7e5035c983d1d10bd40cdbe10017d272e3e3841080da353df35f4687c9dd2d5751544bc56addcbeee428e39f4e8164d0f2f853b1803c5c7cc388f23f58c99480eff8b422b72932115ee9164bf114636fa3bb211a7f8500aafec232b30ac91223ae772aec14d97f4ae242bf946998638a6c4763608184c2bd2b4fecda890d041d2ce844d7301c35a21c95a455b9e43450931a06aa1152813a4dc36f2b9ca71d30118e1e81f5a146f472969e769fd2995fd6b9a83e95ec3e161f87391b5f6cd38fd5149fc96ab86366afe3af855fe9c52a45060943e98d8bfa30f815eb37e4783453c19c1ee704470771c3233efb5b16a482f5affcbcb6afe381b7fde1e7de1ff390ee48cfe4df15a10378787048329b2fe8f5006040e7275dce7419e896e100df8351d46d432ea8e4b9573deb490fe074b186402b299c989e533b3cfbdaf1c9ac3d43d0c5ca8b6005426184ccd09390c96c5fd76ef87989c6d65064617d27c3eabf58ae0b3b73166e64aa9baa9d4ecb429a133d8350aa01c27cb3efc024ee2320ff0e7e3052cfe03e995d9e78448243ad0c8d77bafd9304257716c5470d0765564a2bf96e0bebdc097cf0342fd84d1c042cb3ea5b02d733c4d79750a7921e85c3e5275e8e22dd5ee03c631dee17048be54a143ac441fcdbc7a637705c0796c3470b83c4b4adb3756e34abe4a0172cba0168415308e531c7503afff5bc2de0b6751aa2d0831120808692684871e3c52f17bd1b9eacea7bb99532a0b8fd28bf096564979e06f299667d41a6951f7943ecfe83269533dbb03a2e69ea1865457f6a77223be5d4efbbe275d296b353597f8e3ad7db92835ff175c3329a70b40d28d95c33190d13ed4a3719758956e66ab216e2cbe7eb2e35350063380a8edaf6d81fa9ffce3c0ca61473896705dd6a00222bc32bc6f1705a825a8883b29803382fdb1cc7fdd68ddc2193021bce70f263a62f27499481382877679b294d472f0a7f7b3f7f77b841487921569c9d90cebae86cc39ce0889afb72219ef9bb008f05220fa7cb8e8ca23044d477dbb3ad994ed72e3055910c982c565289d3dd6b7f6eef11bcad3d4bfff036a7e63215ab3172bd342cd309a7ac2e77a8e6c341f13af24a10b37a7432dc7275ee77f1817b4961c6339e369a27f667a3958092d6862b99e1304f1446c7228255e95d295b992fb9bce526f260225382b7f8c22f2daa6975a5eb4808f495a5c6f99659d0a55760033bc36fcc5567a965cdf608cfdfda9a4da252a31ad66c1f3c7e7aa032414fd005a5f5294793015a57a8f1bbe1713789afd9aa2a64af958ece8ea89fcd1f47edde9f336e1aab0e69b9f1992bc8d9e3ad6f325bc59c3cb0f5e6675036e787b7a0e1ec4a73f070cb9b9955e11c1fd06af31995cce1e3ad69387be539ce299a8a1343a860e81179e3ee7d5e5a480e05b02638ede4917d2a1665ad63bfab1da641b3d7cae0625b268ee8346ef60c5a3c0b21930a7b6b98090603172b24c5083b1bbc83f0a04fe6affb225abaaed17ed14af34068cf5a035e8d6bb9658e462361e398db11ed437253b7d5d911236997273771ec8830ebc55f7918ef1214b8b76aa4ece702316be6908ec3bd905b23f3d632dbdce8a782ae8a607af894b42531a2f9390f1ecce6ece8c29df8707a20a52b049313e09d33085b7fc7a2b3c123026f60720379d493338fe92d6d7f75179e284ffebfd19debc6cdcdd051687d48e2d2155b7d8b99d364d82b2861deb0e38b7fd9d69c7fb847334a54a6c16a4c8f3621d81e46822212144459578ccb6c424ee84ce0e8756cca2fc8aa2e690778f718f1cdffb7778dfdbabfbb22c7332526145956313e06b5c32836c2be9e9b2454bf14b854b09ac2615e55c568c8a2685790a90849392dc6cdcf8b933bbc09a233156e5101274fb3db2e425bff1d1387e8e88604485c68c31d8adba2059d7d2a17d00ac95a5e77d3b6e4e99b81de1d5b64c7f3b423db5bef8dd44d44b765e6910adf8b20153dfb7c29f453f048ac092f62d7663e239fc0f5de2615edce01d4f4be50298abf2e170d8fa365662c1eda3178c2feeb45825965a5f2c79fc36c267f1a264c3e7d40d5f81a521f047c8ff69b480d3e99c630ff5e45b8002c13d81edd7cf116476c94233c7a92c6dfeee19c1d1f86a49efb5a6dc8f0e3750e2ec6512afdb1e6dd5df99f4574f9e48182e05948269b516e554438195226b9b5179da2e2c3ab470403b742be5ffb0ee695c70fb551a75368ef86c58dd2fc271bbfe6f8186f5e3492808f51476ab04a02ad5a6c20b46e87137861af9f3292325f53c9c9ce4a5f465171079a7c2b9d5d0f8cbbc5a4c823ee45ee4f14069b597cd098e68ece14428929db132e2d2c4cfd1b29635d2eefbd6d3970f54a49137a0d664eecb63c81bce945b735b6d62284991cafdc1b23de75a7b9013a2a6f1dc1ee43274a8a762d9d1b6485653b8b7aca9b2988a511c0a77762c6523518d55c891b51c59b1374d0f81cff2cc3c50f4533d4503058e3bc665b6b273e91231ec05a45e0807f00f965035ee1c314a5ac9e126360420c8dfe08bbcfa62ae4379622fdc7d00f3b2764e2b5218c7b8ed9da015ac024434ebf20122b27eca72c3ef89f80f6198dc9a471e498f599c8ecc486cae9f6b3a8f0712ad4d961873d84e7080b5acca8bcdc4550cecabc4f8d1363fb6210f83b8a65c7fdf476879b13f79435cc011c20538956a9121c4e4b605e9703921703e98776314e201a0f47155e4b9b33a5c94e74ac113658a43afbdd65fec1aab8a4d7da8b6e3e3f4f22bc7e6f8e1f55b72e417987df59dbb85ea19898ff7745a6394756ad4c8ac13ff384279e352c4ab28225e81fa26c2b0b02f4a1f9bdfbd068d009563388380180f4d7b60112191c8c8cafa97cfa0b61176c8a534c3f817ec3008c992093623b1b5307e81bd53ebabe3d3096bfdd8e4dcb531de37f29c1036cd4cb26b633e67ba80e33c7445e730fad2b65e6d06072bb57805843860af4316f63f910ae6f14d4492cc9fc558b26f40a9e5c6bb93383215c3e38d15bd6ce4b1b28820ddc058834449941a0bf82901c66e73ca0efe504d4a814ac8048e49af4a141ff4763b1a7f7bc0ced2ecd0aa58ee81c8c21354aee9b19f6322607399f6bc3886533688e35bfd403c9a7808cdaf605457d0465c6140b9a544a7708d301a1787830d7349446a12264221964995eb67bbe176765d9ef93c7e909cc185629cb4eb6c5608d2f2d2b491564d5c414bdfe953069b04407f6ef879ec5d29989e43387329c81e0c38509a5f14b0572747b15c44fd69c88fd275279daaf07204dcdbde8690a76405e9ee9ba21ca3f98d05e367b3a1aaabab3c4a4807d5580fee27a59d1903d00181738f824cca80f74584222c0b1025512d9260a13864df08d4340f84ae2eb5db737d54be4a0908a8a7516dcd2f321c07311bc29720dbb3870285ed96100c0b448f80854892efc1eb209d046c4e15648ddb37ee691005a13f286a4d44972e89eb88fdcd323d1eb49aa3a6472348b688941a9b23acbbfa2c2ab444cdb5829aab33d05fd2c79e95a530fd798098def1cce90971f4f4b045cb2b29e3be1f82ea154118877e8d3de5f2894cbed23740c60ea6aa036080a5a7521716c6f6d15d091ee3beb818938a4b848228b1682947461a3d6f4e655bd15b8c10c0f8f83231b348ffcddff9195ffa939dc57623b2a66b064c1f9e3ed391912a4631c496d0c118e79528712b07f173ce043cb82f559d05b3cb0bff409e3a0819d4804475a2ce6434ab4918f3e11a46f02e2429f5845481fcbaa9f1529795e808888338eac8cd9741d107c804f48a1c684ff35f3c5c4940d72bb3a043c81b532c41b8772e5115be8f1e63bb75055f30a91f0f221567d9a5cb427ef8d25838853e22f00d122cfc55287e2aa1cd2b882382ef1d61efb0dd4554e9096bca8ba91a6725d7aa6e1173c979251742a009e2f94c6306493dd50d3d21b16280133601997a878b35628fb2a1350751840e94d511586c958ad7369394a226709003e52cbc2f49c11f0f51e13603a64368b25ec69057a018b76246209b9e115e24d8e0913a3a73d793ee8631849bab702d4e19d62162beaf9a16a9115728f16345d38f724d0e404aa08125a5a97ef32e48a9e8f35c480cb7e41ec2c0826743909215da3843965da66a8bf5d817fb26a93ff2e0d90b203425a0843ccb1ff6c5d4dff963ca3e046efc03ae861af94cf263fb6cc5ec9603b8f55b01ccc1728665e4e22fb2b2ccf47a963ee6b498f8715b9285a88e78cd046fcf4eaca347a34035bb0dd3d9be080e362bd235fb324849ad7458422047d69e414c735386d0496f29bc0d30b358e111a4fcabef7ae21bd836f971e887490522140ab4e67ad6c435ba96472c40dce08f49b3a49e72a79f0fed62fba5af16923231ffb0ff5dc5568a015b260d3a50884efab976746ba6d820a3a27b8aa8fd1193d62ca76feebc0e58915860a4bf227f38a0e79ee1fe077422344374a12e6f07bcacff18fb4664314ee9ba15fcf0e702f0e8168d41106257bc6439ebed76a4c0e7e64a804cfa2a4f69d02cf67445f0cd21bba87bfb71ee5c4b754fb8f4061deb051219f228b3bd7c137bd21a4531749f55226bf07b117db499c850ddace359366151c3671f197d00555082d312dbc2b58a4044a03c0e4ff8440dc8924f289d2d8e08032c9862d49ecdbacb725779d6b98949159b48f9ae339a5581e554a0f5ccba85fea1ef15bb820b673ee489cf1aaa1488b9c1cbada1ee7b8c9f8f6202b8a785495a41761d20cb41f255021318d9145f624c56a12bfa28a35299d014cd5863d9b18d88361522cb97651051d028ba743dd01857454161b58f8342f60bd8888e3c0d229f1a2eb5921d2acf75d5889ecf451c88c6b978619f9ee2d85265951979e75112a993fe48bd736739de8fccb4007713870b90610dfb2f311466379c0cdb1ecb60e0f0dd4f5921ffe87d169e15f0cce8eba5e7bfddf422df0fe2242315baa15ec28c0f9d7d774d39b6092fd402c6a1893a4326a188ed662cb83f40aec6c76fa2a86b8615a4d16623f7e02fa9b7d6dc2a504779ff9a5c59a53cb8eb84068395065cd83b0bab4f4095c7dba2bb8d67f0be9cf525ae04ba84399dbf6c388f68741064ef40fa18d41dc0db17b82683a0257a8bb53a887f3d087a791a24afd11415f61602a9563da62db2b15673e7698e70a8e7c0c6717dc7a2d5d1942119a7a3d32456ead741dd828be388c202263f01a70b2ed3b5108e2bbef2d7be86806ed73736e422631fa03bde150753d1a21ef8693a65732d8a9e1a88366922beb9060364978ec7a25a6f4034f575320a327b4462f69c559d111f5ce2490bff6302def20a1fe031cf1650b08d80bfa7c31ce0ceed9d63c7a726f4353985027585c1bf361e01fcbda74b5d09b711eb1909afef17cc68b4f76dce44478e6fda2c6a1d7ee81847ee196fcb662c2d03ad5c328701b84f6ad579921e9d99ca20fc01833e0c7bd223298d3d00ff3a76da2965b8d5360682f9cad2edf52c6f352aabe49bb677d43a5a112fa5bb94bd440a1224140909d5ac6b91a8679afc43e09215d7d333022e229d2873b7b38459bcd91fdd27e7d3f92f2fd49fe2cb06b12bd938437a645e84457c0b409abc45afb09ed177d1c30757fe1da7acc87f5e4666d292aeab9fa8cb3d5b1df0f2ac03f65f34a2d66bef14d5c3336d4fa09d98d5ec9e64d08ad35bbae80cd7aa7f497336b31f24f7069de4c71e75b9f1ac7ce2837cac06271b48c9184d91cc96372e53c37632b43bd018d054ff04b63aa57d332369e56a68e98566efa734314174979cfb6d4084343607fd2e09b10f55b6a6886afeba22426c19cf26989d02da3c0440e02f521602564104c978e18c56a456897d11bada3bc0b0476cab75b48b3463854706dca3d22f33f7f9a089e82f80ac8a27f9d0beac3794e2b37c190e653252092ab923e56dc74448305ec669c1a320080ec5adf60b760be375fc4cc500d17edd5c1a059bb90399ea66768efb2ee4dbe64a406a0a099578dc317a147046eaa8cbe2436d97cd9e5a36512b98cb236a3bb0932a0cbeb843f8c9d0bff6350d63ff0f65d4efec5e0b0e02f063bfe56803a1658f8ee23c9e21330c7a623186873d60cfd58bb101b2945fa6596a3a5e3f5e18ded917fe5530509f22899acf583b460b24f0705b94117c70ea387849940f838376d71647990ae8c0c000565792df0f2cb3bc53377f9d25ba34d2124fae3efa91a44ce747bf23001139ceba960a31d856ff6ed3a753c866cc472af7f3b2f5ce22f4c39ecfdc44683926ecbb693b2bec648ce27dc95c5fbd290280e8981e9e1b44ca8abe2a15689bded8efe3929199f84ab51d08bb06743fd68f56070897b3b1fa516e22e66f26af3a46ab96f30905096a46dfb59fe5a082a95b4370ff725a2073ceb83f512b9dab98178cc75010112069d8b0b672f6c7a305d5bbc110d79470a9451b045e6819e9d1423783da61862386ae13b828ec3c3faf161b01ee35080f6187e007014c316f044d5ab582261307c4c134a07d19e6a40df1235bd1df43a2e818e0fb79a71c9c91a5918e327a8cd58d266b1e4f574e2e14b0d2ef728a57c876c2ff0c7cb24ed4f0ba9bf14946f7dedda13397bc46d4340a71887eaee889d9437c063e64b670c855b107b2c4f895794c2d105e41eb32e35070f1b54df42214095e63b1d9f1f0b872491b7733c24f04341efde1ace292b1f1629fd636a0470f84580c2d88bf0fb7989ea16e95b9708250336d3c041d4ffdd494bee457d28e5baeb8f7b97bbaf477cb3cb23806532440b8f5a9110e4cd77e02bd9b8951443969da62df96018ef1aa4912d0177c7679ba64077684608d1a169b896d0ea584bca858f8aa83c4568cd7fcf59e6178a12b2861cbf256d0cc0f8650deaae02b00af0434ffce8d424298696bd2dc582b4974eaa9d5a0e8ba2d9e4606763a85af6311730ac8b4be2657655a81777f2660017eb00e4254637f298c88411c67a3709f9cdc6db7ec7131d0382236b230382a813729a6c76a4133b27375f2a5917e398bcac644262073c81c92e281c5e41d2542c298f62ffc4539c8a0f21c4afa8045adf48586a58b0c4f857436ee2a97f944d6f0b41a345fab888358a293c01a058a94ad5937c9957002d65a932df48654bcb4c7290bf2eddb8ea4bb3703ef63b4cc6d4dc64417caefb0495ac6fc6bc3b67ce04631de6f289a5351a8aef8c8a9405086b6058b0f9c06cfbb450a035f2d55dc155d2894dd5bcef8fba336ab65cc78f9006aa78e4b77a9138277393e3770848e67032ca5c17d4f5f6a6696cc422b746488feb9c608e8685d00da0196846367853af1884b312d620701dd667fd322423deea71daf34568d912bf1d825f8aef2b5729442766a22efe829276266592eeeb1347c557717e9c6dc0489eb770cebfb6fdf0b7d62a74c4726b9d73b2bf20633cb4180a4809d82d3e09f8fc543fec068d946d0f67f602fb72835305b264991ef4b9cf44e0ce920e0858e0f5bfc2d13d054fc7b2ff104c3c3cb5978f7d7b61d18d6222df4a3b5bc0dee1582cd1a38fe7c06e58ee86689beb5b4f3f9dde92fa5cfa824738f606a44999441fdd7a0281e313687f2b22188adafd52096bf39827fff0420d1f7d191173f1ea209fc1984f48e2e77ac830661cd7d83d034d42596c22caf75026188927b593cd94dfe22eabe9cda30ae3c67b0c4ccf7370294999f0b1cf0bd6b364c68a522690d2159e8f348abe99cd07cbf08f84d813134db98a66be6545b13ab0b7c26ad8802ce95a8fb2e61133c60e0682aa185367604c774cc4f98828fb013e0729bc0ca09269133697957a117b715f618ac03578372aefeb148ae647555cfb6ccd4efceb3e9e127720f49fdec3504896e62a5d16188c540ac8d97ebeb5726d917a445246b764f3399165a22c638d890864a4ae12a4cf7f0f4f0cb0d69711c40fb99816f2815496983598840a8bcf0a857ff5953a6d7f69cdb682cd1d2a706dcc4cf438e9d2c0e39259e456cce93066a0e5b9aa14b3fe52eaf07ddb19056ad2b15049bf0a8a940bbea430633cdc0ddf385ea65d53c202716ae273cdfc4630eab6dedc6392df6be4219eb0668b2ca9f0251e3c8d628f829ab32476c46153850653e9264dd2e50a50289270b768fa92e72ffb38723768cc673554c4524b023d0b5b1274268b900190368dd07edc057abf873301f6272f9b05180d9208c79a0e141091db17e512e70b968db88ae7e20bf47f3e53f9cc736f404bbed5960963cc53b3681da741663d9792a18083a6cdac1a99e11e410ea655f8ac0ea426ba64b583feae08ba1d4fadd91183f37c68f6082cd103499a832d773222239bb73068d31ffd186e0bf344176719c1d2e457c47c110d83beb2f601f0ae445582b4c9a602c279512060b4181b0c8af1ff2480488176ff6c08504424b2eda0c78392336dd500f458b203e01c42630b1b08659d8c09afefe05cd4d022873c3521055a3110a193464811da452485233dcc762220c8b99b349591157877a9666c55002233ca53734f9cc5e2f3fb05f8a00839be1b7096aa612ea49d97e1a347b273f4386e121539c3bc4102511d705a1d394e06098bce716ace4b79a2d29926e64b7a98c30a893d2e45097c07349bee41749d3386082ca21ecc400662bd9d5d369eeca9029a84cf1ff26e49066e5adf2e0037627a7b0e2655d1d184c5b8f0348b8a33a10cdda20846e305bf4153616301be405460484e55153dbf5364d633f52ab910bd7ac90b573fa7a1b7eb19bb6c643ad647ad8991eda61a6c5a3deb2395721b8cce16feb4d19b57e3509bc18a2c056e53509d881638ca4a95d38cbab3a7f394d769d163dcec54f3fcd945b1717a71b5c2e50848ef581465db7c1399526a03b6aea3d32f67cc5427c2cb3dc07838d1e2f78620317b3f7b31701d6b068d4ebb35a6759112bdd922567aeb59c09138044a86053a6b393f0740e34e603f6a50697060c6749c97f38eb09c4036092b2f509c7da96c54af6e14ef9620649780ea27b117d36744a5d80d6b04c0290abb45e61e51f1a9b71c26b852813d7092c09851a9833e026792d5da3e8e1bc951d5447a3731696df9e418e8617b0eccad51dcb880d1f46b5cf56fc323d6b81b9dfbc8d1b922dca2514c5b8fee64ca91dd16ae304fce499663bd673ae1d7b9cf5d4ddfe1850044f7561a23087eba5b32dfa1453505fd246fab3175e570ce1c9d54c57254d5780d64c17a9af3d32d43b8274bce7812434c6089a14474363d3771dfed35f654dabb0c05fed057f49c1f7b69d4aa65abaefa3119aecc344a29e08b65a5732ff0e7d18827dc207c75344432252e465e54c07201282cc921d3658fba672bbc53c0db40f81bd341ba3e97e79f65b86e705ce28d3ea7901d2422cd562eaf67c3664d9f09962a47049a489dc34996736eb940736b4dadd14baffc659e3873d46c4e4273c28120b4b8dc6cb06040670b3262a553ee0d0ef7992f3fe63df3212667bdbeac874bc553aa53f57a07059ee913a8a97ba98405d004209c0e5d6cf4d6655f43b59c79eea2b93a780e0645c865eb9d99cf031ccaab5d6a32b0cf97ca4b4072a65fee2b046dc284355185a71619d1132429f95b973d3a7c9852c7c4b153497c870dd40eae88eadd6ae789daa5446729efa19bc1e7ae49368da08b78d906617c5369a3d48abc29953c1788af21bce5b904a5649751d6fc502b83a01943133c4034f2e61b20beff06aee594fe969340408360658f70c776598895957a843340b63086010415c6d27672e0d656782ec7f93712b2e8740058aeadaabc043f1a189c284e3acb43529d8443175186cbc70ef2ab51c4f3b61e98cbdcd14528b6552d42e42773a1ebcb0980e076a3d2f220a9020dcabf09039c55f638e4d4db1e37a6aaff72d22ed2883a6567a0bd64ed70ba07eb9c3b1269e6a0c5b57422114347df8f341f1f350b8b9810d2673d8b7d718d38b1ac33aebf4c3795fa5dd4e75f4a684920ff42d5a6c5495724e126d4e594de33f11640761d4639164e3eed93a928ab97ed0699a8c3c018530a049a9ca43688e7b2199cdb63b85d5976c8468aa3c57ffb9ba3819da8e47b28a87317dddf4d112048b1e3f0c66d040a712baecb4dcc4f916984ea95805e59dc0fd1b95d1e27e2f2b324945e45eaf6b4d09b43795f187980f50a5ad7a4935a9841680b5563a6518991e9bc48409a920a85940a0cfdcd1e28d500542c92299d7f2a9b090e1e13cbe4c12d346e09260f70d65e8b14535779e8a1e64554c2bf39a5e8c1b88866a30319074e4f3817e7d1dcde4d89d0dd96c4e7b25bf5a3dfd0d4ec066d9f114cd3d096bb0909ab702e07640d694d70c4ae6f8c15d60f20c3053e781ea6f3a1961f470cfbc108c68657b1782d283a163d928b0038d5dacb11a32917942c40a73cbc2e4e9972cd6eda602949ce4dc0587773a41b565fec3753f1cd6dd2233e9ffeb5c1dfcd9a574830a59f70b55bd56bb7ded64743f16ff39a45da7f44c97b99281368785423da14dbcfd6f3853e0de8b6125a6583b46246d468464cfceaf3111d32e33b705caf0e517d16e00844ee0780a19407ba5b9e18301c46183c31c5cb5393300f5f8f69cbfc262fab05521f1cbd3793c7558295b833c3408cadaffd2822ca635ae2342bfd571616df9e021debe19a9ccad2ed8198f9f22ad7fb444eca6634ab0877de1c8ae3a222465f79c0f0dbbef37928cb8057b049917c902d84c61f7a3f7dacb7c9075ed187ed6e0a5232572752d08b2ab870c86d7d4cd3b9fd8c26c6a265c84e975df626d33f2adf5e6b480cfa9c456d30f521e3ef3d0fc36da1728e3dd75a6ae37cf2589bebadc7a099f486254b6ab52c0307fd0a387c90a48399319ff61b0ccf7f63980dc35658766fd68645d5d5c43df50ebc0ca0c42644af1a7f6d948889d7db7779498183bbecf271042b3fc869b903a5d9550d968108c39f78b8d33e612d8faa20463caa42fc72b82588bdbca2ec5b9ed1e3574ee26ac41787a67c3dbbd8aba4e21bd79ec9e55eb1b1805bf1bd827a8ca340b448ddb96495721c7d898a2f0decb0402e7bc3277bbf4b0a3e0d302412e870c376f1e43fd41fd243985d368b00af026faa3011311c641788ec071723f659a0653813c95dd8d5bbcdca694a8ad79b40e8003cff1ca7b22cb121eb4e28ac17f0f18df74e45e27f4d759d1a2bca73c4bedf857071ef74e01bc4874ecd1f0b1f2c568aa8ffb88f384819fb0617098e445b1009b72de93ecfde49c5791a7ae41607720917d1e51e412ea28e18a1e6c763b656297a42c61b93369bd5b392d06d2b3cc30e8ea51a7d0ca7ff4116cda9b77386b6c65cc3521d444d5fadd692c1becea2bd4ac418b51c2eea8310b65f196d3c7c4853539a815d2edf0977bf4cec9e2298ca8b961fa2c797d67135aa8044dafecc1639f37ef390845a69aef314e241b3a6ac9d3b62e97902c9e419cbf870c2666c4abb727e8f1df631c5fa31c9f02173552f1171854c1a0d8ba558b842ef17aec245d787a0f283f39975804a5d4c4d1243b1c89c0c348c5b987caea0267b184dd30eb4696d1f3121b26fc02494592834bb3dcd25043778df425b993d62b9df6b215879f510129e94b0408d2f74521a12ef49bfb807da19e55dfe4d560d1c8728e4d97608cf6f8b010edc0fee07ed681201435bb82214a1f9b80e5c5f39f6069e7bc624e22c2008d0b974fbd5a152c08215a6cf18f324dacc83e52d818bb8e30f0894a28eb0225f144e0d55534a720515a578a9e76fcaf42a9c5b3a46afae952acf85b30f9560aaac9bf40b9a8ed1cb8095c8db60c8a9193e58e9849a89ca34bd3520981251788525436b9cee0a5a5042432dbb958fd8fa76c0006fb81a6a7a0f7e808594f781326c7469ff4c9cd5ccc80294a291647e69c08516cbec70740078729cc206868354cd07407adfdb506d07e955b7aad4649118d744352bef2c6ee4f326fe0a103ad117508bc36caf99cb111c3f1d55f2b5984b3f8c982a86ff906d6fab2f4a471897b09251f75f3076077af7a017e9c33fcf0b4f17de4fd6e65f094a4b160c835f4b817d17c4da00b3f170948e04e2e805a60d27b6068d22009a6ba974c69671faf5e8274bb165747045b3e4e0d8f73a2eee73781ee1ee9b434f94da45c14676569bd90815c114180e3e00e3c9216d27a675cb16982d3a958dcb8ec9ebe61f8693d6b48cbde183f0ed351a91d48b9eaaff0439b0ae95c7e81c87238180e13a9c774246057d1aab62977b0d45863e949ee52c3544bdad98325f9075dadbe328a6cea8aa017bcac8145c693ba673c5c0eac557bcd427411bb455132838f2109c28f6cd3d15f48adaf857b93c4bbb20624c3cc55cf1427be9fa5e668fe2c8e7fc25fda696408ae319f1d17b2ac0bd0c8dab5f05de608548547ed497f2cfc453f343473b727e2b9c1ea474dccc4a6b995c9c5a7a0ddc776e3b84f806ceabd1511807f5bb1ce71cbe4e061435996d245adec11414bb6f30bfd4c0c23e87b91efc113e64f7cb78501457c6cf27facdff24c0673bfdf907d7aad6eb6368da429c8adf6daba4154a8dfa261cf880a4009af8c5b282869d17656c70e8294c4b2d84ebaf48754f3178ad5abe5f685a32dd1e4ff1a715b871f3ba6b32a6958ec5b46e6e68627d98396ec5945a11cc6d9cb82f63d3cb96b1da20fba5353ab04eebfdc571062544b27e13f2e71d4c6d47ea12a61e13c45358455005b65a0de9a32565b3ad92bef5506bfe2c66e0a9a602b0c6d6f6b18a1431e897c1cbfe8db16eed2f6a08c39af155ea81206ac5db019c37ceba45dba404d29b63efe077a8d336dcc604cda762fdae541a8afb98820820c3c9d9c5e7b819354207458074886b0de452936167b931631d741845b683248069667f90078e984b5598f9a91e1e360f9e0eeae35cc553b4e7560973a3e38437dd1dc947ae423d7735d8ae036ef70c7f2a4901e5fedf3b8e116bd12ce17c34fbd2ceb72c87f5586f7b799d471b9b4878a8d2d03d3d772ec67bb44d14e6db2d09fc408115de7c1d99b8a2abf232e05d214d703a3e95b34e954247bde80cee4ab8f9c65b5d4fbf214a58876e3cf5741e588a5743c7fc0e81a35d8c03be38066ddfaccb4e29d1f9020035529845b0ff70fcabb4cf3d8553400c330a1c43514ef1164a2b232ccfe72f93823680a5cb6d06b741baeaa987264734a9995b6c2eff0c4033210db55c3fee1b541c93ea4658b65c43874660669c0b62cd0fac26ee5873cf4603972c9b2e396c55a49a84981d4968cb8ca5120c7016ab5d33119652791435e8b15616e0688615d52dc59ec1be3115986b04c55caaf8493296ca5ca45e30769fa9238fd37ac51576c80681134581a40d996293ecd5f4c321a91c9ca2c9ed298a6cc4e2a9eb61b78974401203b39b9af127e47159e2616b7451284967cf89d7b8dd19cf8b4d3a3c625352e23996f5280c2b7936b85352d2b3137c7d6ab376bcee3fc4d46ce381daca60249fa70cbe672e66f268d5348142a895d86910dc0b95abcd80672ff58303de0fa5528895be90b5cae4d54451095ab2b01aad0404db9e52b066f8df358d3a6da27f3b8a6a09fe5a89945929f5ba850c0125f78b70a6b4a4858d9a7ae47e25f1398559445f853f535aa050a1229e22de080c4ce70139a610628e420780ef44f9e26dae743797ae015b225f36cc35b86df7a3c277ce7fd6ce1ac045cd6b167925b90bc4c1b1d769750473af12013daa8d5256024d700e9f214944c3ae453b99b339290d958c256ae5cf95f2eb08f52ff70a05bb4d4fd3e3b612c5ade65e2bd871d0f07c6bc953543e5a95925f8e0ed0594b6c9b776cf54c516cfb5f34a4d4ae41387bae2f25c3663d85d6a740b9b5c68feb2f5674add23d1436510198b7b7b798695896557461d8908179c93f420b2d0ab3c18c3b7cca1e70465930cfbcbf25d0fe22ccdbafd246c459651fcccb0537c1781309f66d228e0796e82913527ab847db2f40a53b39ebb004775a0f4d1123d28fa53e472000167803b15c9d102ca1f69de0fb93dbae68e8e89ce6729d529792d66ba7f2b607907cb70dc589d6478bb43c5c4abf3b2e92693f2ad5943084439c4a3a243ea2083a7b3338b9ddca17728c7f1a3a77447c8fa5cb4559bb387abe214f97c5636900f2748888a7b8318a3beeae6d0a619a1ce2bb63ce7e70b357ce7084b38165a7c3830524bcc8a95df0946914f2808151fd5bbede5f4f4377b5e23b489291da4b74fcd90dc2c38bbbfc3a8cc680c11be31230a5e30cd2859f16b3bc90930e7e659090fbf8a0f449cd4a22979ccbf607b2c7ddc7155deafc969c0c73d82176f7994544ba2ef154e7d231b36b5be52f888bc9a1204ebbdf46651b4484d45a872565afbb1f06216c0e1daa4ec2a6dfb66720f4b71facb2cc78884ebd6207fb408d7b597091e5f711b24950c2e1d419aef0d5c43dfbab0e1b64e5417c9601def562167fefa84d72206c679d77f29e58b78bf7002f87d7129a256b72e20876da0c0694251e9544fcc299a5e2cbcf48dd5f60175ba35b262c36dac54c34ab231b6e1bf4c56ff562e28ee31730d5a3f75873095d9ee02f93844e7c2ff9a04f09e8d0a1a69c61c2dc26ba9a93899c4b74317b5819782ef6c4276350f2a69c307c33df40578c89979e88d097a74d6607ebb41ca673806d95f8b545056711a6bb71e434d6f148fd5fda4a423d273d74b6cbda16601a1f75f78357195efd76833c44eacab35401d3a22dde139ee98ee8b981fca673a4d0a6ab362bd2d598835b433d729d0d75561ede78f0113434f324cd50ed3dd1f0143f25b685501573e5b0a2b12f1477df1ea606611c0da2c9d67c2a32835809f8a6c2c24c02fe5b16ac25d53f81cb220b6db8b6e747991b1ed06741469f766f663365e7cf3cd93eb6d907adda9d0880903c709f000672551b00c52b297de6a76a4a50880be169b8022ab9eee7f0d97d7dd3008bfc601050388d75a2f5afd0423f1fe75dfa80e39af50e712b717846b8f3c7f45bde729f1fb112ea13c4442cc669559998eb89164450464287d10f474e76079b1daf8819f01e29b70fcef616a17d4e8f25c20890426c91faf28b89aee6ac3c528e37deb18af653ec28d1e231a5847fce369664599d9c46cc146411dccf59e4dea19f12ce1791416517047c337a7b4e82a04c91df5a486ce38fa58052be578dd4ab35fd9acdddba8eedb1a37f402417736a68f90362f03eac453f830b794ffce7b03d87cc3c68a3e696afa882692df60a85e93b0b2579a5e178c9a26e6d09d52a804c34b483b45253d16c323f136262cddabaf34252301e6ae663aab6584fec44dbf34ddec806fded03f4c454cbe5bcf0b486715c70b6f0586b3e086463019acfa6caf1d2694f928ba2752f5a5ddb8b1a5c5e9bec36f5703ba5f1bd48f82d0df04fcfc950f08da720dee4cbabd93b210d9e38a496db18fbbbac30e15a1e29588cc19a2caadfc01b6f559c0d0eabd4a67d3d3756973b4266e09f94725a36536d3b52b187e4d316d73aa5c0da36c8cd5d0fffa696e926a2b15adf5a97ff038ab14f8eb2beec91eefdc613850868ebedb2a3d3eeb636d84c5d63afce293fa8864593d1e12fcbf4bf6e770585751851b2aa9a79d6c5dbba7168d2e6659bbcfbaf5105b8dd596eef0798cd2fc42bfbc030ae023ef02a99589fc0de3239c1ad9925b9655e3a37772a132a05c5c7c5d62ba909769d42df4229628a0a96e0fe44c192d0617b52dd8c1eb580346360ef897dde52a471993b82aea947ace926bad636ed6946511e32e713b4626d97ddd523a69b346b105b7bc2c4c3d604a996874ac9e379c6e347115ad3948760581cee6eb3698022e7fce2a8098b54d5d0d449ed13544028d6b34293ce1265eea5a6861d479ca46b12c42a118b73e0425e8ff0cbeab6b5979cdbf5efdec08c961a6495e52c8f488d3c221f1013bbdb3ef8de50d6d753515e5c585e6ea5780d715cd5df695cb8c50ea9702a0ee9972bf3c644bd31ce49143af48d7accab2bdd1b12a5fc5166dfa4bb1dcd2ed7ad820a7bf9c94bbddad58f0abeffc60ee5d6f5a5f370060567ef6ad3929f4a3862197a23cf29b6e6db93d6be5309ea6ef3a9d742b9e75969b1ca6c25ea490b060fa963d0852b1040779b64359ee965b75c60edf6bf53d6d5e64215848ca7c246fabcd740777b8b947ad3a68a2df141dc3660c41e57d2da7784489bc93c02515407708b816140a4b58885bbd386d92f79af64c4c49b6f646fe0150f018d861775b0d89cfba2e4c6501141a901032c69d7dab489bb039cbb7d0d89218f71a4a3bb9754a40e700f76a3f32549457408f6f172252d1907408741b5de0e1b702571db87be0ae9e30db17ac31264ddb629755f35f18c2eb2e6e3bdf529832892343175878d261be66edf67e18b8b47a221d0c8e6788bb7dbd81846b739f34865e5864ae66e4393803da97899bb0d9105eba287521f226a15c20b9baabfdd9d6f7712c146a8625922ea8ffc2ea58e07a82cbb47c2dbb6144eafee1f7837807ac4e85c6dab3d40a0075e39cd417747968fc2247921b5b9dbc4d730d445fe93d0a062b19dc6ce2805cbfc113e6db1697acb9f73cab689f3053119d0b1550a5dd5825d94e2b79db7cf8d8cae97212c111ca46888fd71bce22ce8860259cc1e598d868785660579627f74827678d501d37c0181d24ea763ceb25d988b3315ea5a0aaac2f0b7c2099ccf878175719bbfba293b8ae50dabad3db7a14e476091dcfe0b457dd5ba3fce43c8b492e832626df79edb8bddf6a31cd8e9be453f4d06937b6eaf5d68a09b36f82b5d6e50a127216c2863f295d27974921155be23442a7e2d82ca67853bab2e6e2ca42167dc8c2d182e864ce8d358b055145841dbcec81586634181ad47c9cc6d6c830c2aed129afede07c57d9fa0a3e0c6c7a70077c09d4f060a05155b332709892aee111085eb101bfff9061f6f89b1203c1e3891c4bd4cab4b976947cc13060488346191fd3eb3440c7c9a920d23a190c121f6ae948d9f0bbe93c3edd7a2f70826d5cb8bb3864052a64a9d9634c814f6df9009595c5a3bd7dbd7729be5645133c75e5873b4442f933775259dcfa762f7b423f20c71b9e1e48dfe3e25e908438355a7dc3b52ba0413f6938f9f6c30360101c1aae083960843d3692b7db4772376cc05ce8e852ea311b2d8b57113be6f3a7c4f604998ce6b7c567016fa0748292fe8695770bf8ad88b757d9d16d47226d310a44f57e1eb323f6242b927a08fdfbb35c41ce3b0857cc67b52cff9a73a69e0a155b2644e28dc2d081d2c6f6112e9a2549c2bda39bf878b69b644e4234a5cf532f95cf5c88c6f17c93ead23aeb09ddbd07661fdfe425f0ebc67ee966a3fc14c7e4b83b9555b3c2d8bb463447c4fa3b36c90b484bb8df2c9b79e2aa21d8cc9aa23566c4359c6d278ce09ea58b4c15d21db55aaf0d2243a6342c5b4a58a43105dc61fa4676612663947de60e20028447346c832be0641ba7e0ba15b180e092ad373d025b461ae48f56d605d7d3ac00eb7d8c027da302c611d26834e218a4a69e1587be9ed94a2e1d65570cb4d5da7bbf3855280831e03ad774bdd629b95ed1620ab186458c62c758bfbf3273e16579f3e184e7f8d85272c8fe334ab93d90a446fd6067b051748722fabfac340bf8c508dd4ed15d202f93559aab061cdfe174580431c69115531efb0ac1179c5d55d6037da291bcf904f151ed2eff10aa92ae30db6b9ea364b78fe3bdee7a36a19df26f5f8453ac18d881850beb1dd740f7801aad32b5262d7510fe93088e82031b41578f9e5e452dd140cbab9e0bc07ce031f41323b3ceb701ad02ad5e5a289ade7a54b43a053f178ec98b59f60529d109bccb5d2c88ccab83905513041c6e347aae5c798530bd64d901addd1ba3be1f32eeb83e00e6c294250de963dea8cc3747f47684f6d44364e20d47f7d31ede69d3afa412301f55a140ef76f794ef5410d264607648895a316d566201f0026285f673fbcd48110439658bc0617a22664b39a38e2c1a4c88afbd3201c036226918b8e8590c1c75b5c45aa1b9081ab43cc2590694790057afeb2221ed3ccf3f728e661ab00fa013d297269e2e27c88fe3c000794ccaad8b7174e4644fcda92077378496023479922168a647c27f1ef46fb4da90ae8c0cfc105b9ad234301714824f96d39c35a16dc7ab62a1791faea9f00cbe858b102b299c9f133326a0f5f6a221e3fa31bdbbeadd605d7a5e980252278af026d125eb25b786c86eda16a504b9908afaf48dee28134be914adcfa683dbc28cd22130a81832f53163ef2122366933ee1f85aaa159630c74122843de12a63e7bb9d8e3b073d2cad42b056416dc55fcfe191f607e79ec7487f143faa6eab71f9976ec11d838db9705a2db8b3df1e0be51f580fa33df6acfbbfd117a21d7dc0f5d0016e44929802a2f72a3ddb2cdc01a982c7661d05d94dff3c08be91b3372cb0960352501b6dc30b310779a7f3f128796dc2199a69d6930971f8c0b6f40269178ccf867019c0fe54f73086b6030038a53746e3ef5a6d482c1854c661644a829a5f5a26315ba7d6805fa3892484cee91f28f57f85acf0a2fa8938e1355c4f03ad01bca2c9ae31e56548f12011a3e615b053cb74df2ebd434f0985570ba277f7216a5023a33b6949a3275e91551e9c24e2ef09b42374f4e102e0e0eb766335c5729cc0f6abe8ddccb38e7d8f82479e4df230afc6853e948d50e92cb83e329d97eb68fb52a635fa25641fb75374b611a4fa0ebbe576194a40121cc27edcaf80a5e0d386e7e5b88b2a1647a07adc924d028ec270b04391396d76b6bab98c46cf7b580a6637d0d9032ecffc20204b9bd373242500eda2090cf7c3b074f7ad736ec11fe24d7ffa7acfdc48be7c3f43ca66a3707bb80e7f0480ce2bb693a96ee8fe6cc8861b54b63afa8e849be10f0648ea527c9976f317615e7c2c262ad25432f888c4e861187db10a3189cb48aa416d43e22880ac1c8e10325ed36bf9f53eec82f7c7aa08502cef0c2d424b8debfb8f8d6db6e2808ce858be476124a698474242ad72d8642d1634bd9daefb8bcefc28345807b7217c20c6a7cfff4c0cd79ce186647460f3f888bc5b1906bb7600898dd2b8f60dd79d6b56206c2444fc54cc3392fabf4f003f00d338ff3dbf399f45e85be192960c56630ad242773992d2a6d857db679fcaaeb73eea03b1599199c43c7c584656c7a849ec1dbfbf27fb3bac6eb53f83995feff76c84f1b464037755c7481931cb1f09ebebd3aee798d24918d191947f78927766fc27da24b6fe68390f6973e333a56b4f3c01c5d82b3d0d635809ead08dd173bd01a8626acb05df09b72649732977b6544694d774fd00c72a93d4b240b269ef5c50616312b4c719746d162c9b80d3ffeb188ec28fb1e737805c1097b4ed5f19f1013a28dcb916b5166d5c27fd4fc19d21b615e19a81c410d7bb2ba2852783be1420bab3a0e3f7479c026fc96308b9b83c01ab614077c0d36b05d0efc5c6e53473af33fee73b1559dfdfce11b88fbc94322ccffd153b3a3f7ae5827a542dfac3ca1d709ccc5d5d989d04fad9cd8e803000d6954b18e21441b0b28fc9bb0d101fafc7cee41c4fb78ed34613f79271818ee881ba3bc0f980f4035c317bc1aa17bcbcddf6dd7e2856172fd7dd93db2aa89a2c4a859c6bca90edd71ac895ffb4ce0243fa1e58caacfaf92ace6c9378c09f1af898c47dd8f36733c121d3ccc2a0070d017ba8b8999b0ee577e85e523b5450cf2b7b2275a59765c1b4cbafc390938a2e3ac0077d977e3a49a3248f1489195036334086703c330adbbed90dfb761b11c06bdd5a515b7542c5e466f59cc541b7fd8b54b868d58653088a84fabdc58f67a5e48f12318d635297032ddfd7b0ccb02e5ab929f2d2a8368eb5d5d456dd075a3f9d6f905f8d22fb66914613ec2f186b6442f99dcaaf5d4726bbf8fabb07d9065f6899f1d71e17f3c669f36ed8746f70f8c869420600d09ee37e3bc7c4af6b71ef203c94ba5a77b21d541a99a1d3af9dc8e2d5cabe30d4997f08f5a8d6b75a6c35ebf0e6a81fb20a12dcd331cee710745c1f9775efd18e0384ae0329fc332b281a14ab5c0686df496c929945d674fe462e73109ad43ea8b2874e1fb72426fe8bce096355849b3abf865dc109de7eeeb475a4b098c576f1160efbf8cf36986d60238a2599d22b01ee68cf90accb09287254fe93bcb568bb3c49b75eaee1c001a294b2f15f28f59e7627a47d9a888a33e0f8b6490235792994c5e86c927455813419ef1d0fe5f5460730d4e18662e6dc6be9843c829a81b38d3e91fe5d8cee725f5b26fcef3152af28f3c61ba67021311aa57dd08f30a427295a6ede923115fcffda7c5df489584ebd03a4df67354267d996baf3b5eb66ab37ad516712e8a311355fd5dee49994f78a19b2440b22bfc9ae978338d914b5418e327292ffa46ccee2d0fbdaa79cfdbddc5eb4ecd1f9153df1204a8f590230dd2939ba9b829e09419c4a1e6229d8f57a034e3d6b935805d81541fa2781994648409f47101cc1c6c03ea8720914a16c72ca505deae47a169cf5503501ecf1e59c927b419fecca0b6bcbe9a6f2855741881b11de22031b18389fa67a75c55e56f8abe3a5d403331f086da073e2fb61e1883052b7c5065a0671e341e1c819b83488a4b8e4c30030dd803f88bd83e0dece1d808e60a7bdc2cdaba662f5cc936b238ff488fc8747a893dc6e890168708e2dbb31a0306c9bc2a4e30aa2de77485e12d764e51a9e36827ac2770f81f5b9aa237b59ef2d446f766704df5e7443472ef8ef05b7e8cc053fbde8b65e549efb3ebd4af66637e136dd6ea88eb199f736a477762682df5eba4d97bfe042e59a0cae2a4730baab6590f3c1f025acddb9e26525bd7e3c19ddc0d4b3efc5096cbabee540b41fb2606b95b9c1ac5341528d9475bcc0ce8a086e078e4a0a4e3ad2bcc1b777eea1e0cb3c5489c84598ec1c6e135ce0cfb2ad0c342d89ca5e8f573a60f5125aba59bbd7d25dc8eec08ca0dea32815fc14a5a8748711072dc4ffdfdd0bc55bfcbf48fd5d94b5dc74e38518fdf57989a15ba7770cff5200085aea3c5aae1b84e20d9cbfd47fe9d10da55358597e769fdbe730a93702f8b9e8a05666575b23546512b75729b25ea6d832cfd6329bb34cd099006a5b4ef507d2639a197f2003a7832b21b5e1a4e1a219aa173dc4d4dbdb20de6a1b3a3c7964a7bd463e82dfd4db90b6e919f89c1096419fb4a67f5d0b9aa539ba1278dc7e9c0d13a646f86a8743ac20d26b27e8771cd82ef1ca0f66ef5c51b4e9c13c163e836562f34d170e0feadd6035a00fc62ab160375203e73e3b25754ef05a5060416228747a18998619f2c6fdd2c8bd1a667c8a2f25407d01f932e72d55fd69ec56acdcf6d1c0fe6cba03928c126e70d62bba8380d6960fc3677b353e95043393ec1e55fa6c70b5654fe930d10b7e542ac6982a01deaa67e674c409ed3eaa146fb392551830810899d83f7ed05dc86d75be483fb452e231dda55de73283c0ed0a1edb3dbaa44f790b6492a9c4be4be2a87f5c0ad699a0d5e143544151e6430e59dc0fc53909ea0010711b5ada678841c7577851afbb7c57cbd25f7e95d8b5b32df6e058471c4cd6a02d1cbe63fb6530a7b6c6807d474c458db36f9baddaeacf13ae04d0950517f2ca294fff563e863569784538219882930a8d94cdd99d1300e44c9978c0d086ba08590f12339c85b87fd00f00a8f094e57a1262608cd2ad22f0ce93cc2052d8090b6e1802d19de42256f3d24034b389c027e5ccfdeac0fcf91f9301729769162e6e849785d37b77af439fcd4c7405821fe26080eca3d0a02d40dea095776e35865f181a2aaab4aab6551094e638c496b29f6a71cb2567e741bca2e20932dc96a77b1aace399ab78f599ad5a9121e8261807692a40dcd940adba85aaf8096c3b33ee9857518c8669aab34a3bfc884a940f7b79c6116eadb2a2156a5c8b29f924a9b9909e722286abc2da01eaa3408f084c707473dfefe8f2c5455a5382a01d74192c2ddcffd53f3a17d921535e9a93a862cb575462e85c1dc40529f89acfd6608ea5c0eb846b4c9e07330dcc967cbafbbce5650f03f24cbd55d2d89b32277e4aac645491973100d2bb196d7444fae3d147a35cd4932715142f32d4df4945d277bd73c0ee3f605a6da291b7e024014c1f154e87af48c9996fb1fa6c907dc6638ccfce9b69fc731a9847ad72f6b4e16330968fe1137bdbae07ca3ade66d9210442f6432c3f46eefd4fef16b25b00ac584bc4d6b39077d6eef4ed7647a7960aca3caa2b17122af8d80be4bbb1946e5b1f097a0e1520ca6301e33310215e1051a0f71ef78e58fb575f5b8a49635823df86ca3b034c62df7f740c24b57cbec57ce82c1a47d004d8edb0c4d9e35b1ad89baec422cec8b142e8a768724e1451f8c15917cc698baa6bcd59d251188443fc7bacfeaf0231872cf9a3f3cdd0b808520970ea65a234f8a30c0ad1c9aba88c30a293750529b23a529ca225368365fce25099ad7791df2475ee48253a3000680d2e56ab85be576da43ff930f5fafe6bad3fffe4a1e1211343a701c625ff4e5fa32dc2fd73ea4a136a9858a1d82f30ef3854e1732a4ff910a4cf23885ed66729699fd2c33d2700b68050e862b3962f50ed0e9dd7aa6dcfde2e4a836f94f869b477be9759d2541c7044e7e6c84fd046a79161603c9a4298d1c7286bb0f96ed8a4221a670de612b8e52dcaabac196fc2e788b832211f28efcd2cd2ce5da8c75fe79c2940121c2d90787328935b9cb4e444be12401b5bd57ce6e217e258ef36a9733b63f9f269000a77a9c925b49f2288efd805afb98b4e50036a588b42d0156aca595bc123be08a4aa1df982021baf8556ac8fd8aae9492506dffb8610146484d4511d6d8a51b73f83c5a83264915632c2483810e70113db3537d1ba638417e98f81dab17fb17a00ff53047b30bc78004634ab33ae835d5108bb67443780efef4c742de34703f0fecebe2bd3b59b3addfa733a1442c9b818c14e8b9acc12cbe85e2b2d9e261eb08df8e01fb4cdbbdb4c47890748c6a1e706b06b6567206f3c96475da9820d310f8feaf03c8ed3df22cdf4007e0e0590062610bb87c5e373f4b3654c89c202e4ffc46be85f86a946d07adae8b36cbbaba98b557168909178fa499a4cb4c4e1776428553e5427ecea9544c15eef71d3112cf12d73fafd57f99e50fdcd14da63c4cfbca899338d164215cd4c003d9217c2d0a74cd464be033b0a6b5b44da04ea26a0c1a5165aee67f9a9f75fed7b94117e40cf20efe0bc595cd548b4288e629a4125d8d22785b570f25b0db90a30298c784adc1344f98f59b43b4c26a0bf59849bfe59e8ddbdb280423f640d37bda01715a0b4105b9a802907bd3c579a222a8198df000c7ed12dba55597ef2f60affe3e9095ea4538d804a848c0c4439975f11104d5605f88e5d947f9dfdcb199a467a98b07c09b4a9d4c3d4e44f4e029e0a57aeb26cd8ef1bfb807bfdb2b00f9131f4f430eecc809461b0875296e00856d8161d30e681e83c65a240844c972c29801410b116a8a0b04781dacccb97508d2fbbf439b5697c65cff8f1b92c08302d03d9434080f4fc161a3ddcd00f75d60ea2c93608af577ec6cb1fb2dc43e055d8583c010385fad90873343d5104a17955da453d466611f635794a68694375714dd36649ec060772c1603410fb0c8de47d9950a321a992fd32f86d30d0e10a26e5933fd03e7180664dea27a0927b4351b811ac2389d0cb857dc599633b246cada744090a031a7c659ba8bf37f423dbeb58acbc624420c2f796301c4131161c3482460f435b74269f1d56ebe9d798ad0d40b56f6f3d8fd16cd28e48c8d2525c0ab7b8731bd8b1fb6f9e692fd1e9be6640c01d941c9ee89de0fc3f8e9b9056dadb94c2dd7f24a7cfc35955b8381fe9cdcf323ea9d8039d4d7e2bdfc0a7b8c84417f8e7f37d9febb69f5e861ef1d12779f2574760bcf95a80280e6d95d5cc2044d2a1f801f04e87053f7aa097e4ec3533b2383c797e818b3449316ab54d86ef749e529898d7869547d7932546fb781b47a30b10581ffb62343146e631d8f6810b10e2be728b3b1f88dd3b12ba3463e6476a8ad6bc1e3bf3a26d8c447f3412b2d37a9c29554b17088a41679cead34fbf76300972d7d713eeffcff5ed0288d308d45d616e04d7477333274f8e2424cd99d159a251ce92632970a70ac014b4b1c655d5652d93c33c25886a8dc47c03f674b1a591a431e92cba547ccc305503ea912bca8c05f987e32cfab63959ad0ad77e91d31d3df16abb6a6b9b9cde6104f7379872566f448454c9aa62bea2dc6819477f1fcd8b06194b9753fccf0bc7f4da0f51d011565135da1e2cc40b29dae9c40358fc068cf215089490a6ef204cdfc635a40ecb8edc51da44008c5412b62e5857f1548c4e47c836d9573cb53975fcb7e17e5e08891d830fc57e155c8b0c860091c240bfe98ff0dbc91ad5661bfaf1f3c3962ce940f3f2c1a689fad72f5feab101abe008c81486363e4da83f1390367bbbb63b9ae3047b73db6ebd54566558aaece0f9e77da1a3d94177c1916570de2ecf3efcd7576c2c4dce510b38acf54b733303092cfb9e4b2d149ecdab863c84fb4d446e985eae7eaa455f875527fa941288fa8af3e30069aae6fa5e50bb2e6c9364a784eeed5eae500132426fc4fe78e189d70061a6b31d510881454b292db7fed7a10b593209634330aaaa3dd5ba4a6ac8781c09aefeb2ac0db44ffacb12e649dd9b9722f81e13c9bf69d7e9631352700f6c86f865092ccaec5115594aa44cce1c58d66ea7a4fcccaed8fe0c5654442974e131735287f1524e95a93d021365a07ea3eadc1a47146bc03b24a84c01bd06072720290441c86a80ac829114e2e74a017f0983867363d9280783a05c8299ff657047d01e6c553956587bd087715a10ff9c24baa07aae76acf8684ce913892ccfdf45e19a28a381a8d81dd4c42a23407036adbc37af3246a7954a316203a2174eff2253b8f8c2ce054f0ea122ec488d50d897357b2853815705906fb1fb48b7115609c985fce7be008571845bb09c3ccaf23f48951e3e311b9517e78bb2124ca09c2fea8856d2f7074a67b04aca7c41406a42696708401b9f130d0c3fd45a3b6c844f752780f7f1173582a3472ecd3f01495e2ad74892a119cbce4013f49a6b052a2eb31ba039810c214d7591403808d2c64bd596f791fe67399051e27a8fb98ca094ad5049a15065b943267ac82001c444a4472e77de015784a7a4186cac0dc0be9144195912418662aeda144ba30b229a78038486c01f10959879d8184fe1d4bc8e6724d449eca7383dc582f6d61ab6e7f12a86959e8f755219caffb2685cc7b48102c3ca963959a22a03e9b92207ac4625805500822c1ba37209596e9c95b0033d5b3e54addb0c13ce81ac7dbdf3e2d342828862732bcbfb7fbaec0b86d887a1008d8bca993006e7ef9e402701dd93eb229f7a7cd7dfc3f7e9731c86e8581dc6eefe1679b11175e7610779df21d70a768e7e1f9c97005d7e0ded584c0181066a29f41b581a4e3f3c268fb2717c880af6b0065c224ffbf669298135f85df4766c2185b338d653de91fb98d9a13e29119557440b4945de23478b89b92c842323dd9bbee79c85c9887f450244a0a26543d1d064606bc1fa0f4f7648679a146ef0d47c67d328776fe00335a265ef2f244564cf9b78acc104268145d9f5b8631cf02562314c8e8d1786045402c1b5f193fd2033d9cbb5dc9395816b4834e217f5e9defc3bcdcc01c3a0b148348539c22b1dada035a4e9dd4795223d7fb8c243c55130abba287cc0536d937dc8071d45151f5c950314aab1eca5df5ab00023e25073be9d26c4b4953123c3222bc424d4e7a1b873dac3ebb48576edfb853c9516917335918ec78a4115892b8f39c1fa1a63dcc645425175301ae04d1a8d14324e0b09d2dd832bbb55dc32aaaa0d0d42f2bf81eb2b994c9fb70a140ae06b114fdb3e64aa3590028faa427e64a24fba88ecfb3d211387b3c59491d0ace391120dc5f400be22352a05fc79f2a581f74d4c346f8c8997707b6ac830acabb9a33446daafe2c03fc90152479dfb5b1352daa09701a17c8703477e6cc16cbcec8493c3a78e74ccc84e45fa30114bfe5d2d2443e9b0a299f4a6163894497f5e43f9b7566414550570e52e4efb524b8e027bb84905022c945a65753b0e6b5b897d3572cb4296bb41ce2f355eae8da84213eb2934160d6b1ff1d5d630e9fbd0cb9f6acaa45bc784dd07171c2145b908b8dcb1b15ff089756b63237d48a8a5d483199d40a99a2edc09230e21c7e6aec39d8b33e0b3bccd5beba6eab6b8cdee530f4111c0b28cdeceac80e45f65274ba635bebd2e860c99ec9747f280d680c247d03e94f428718142aa641e66e7d51fc0080ae4de5514b84ddbc40dad028e51cde889cbc0c5711280a625d0dc867536d3700ce035017b2e89e08301819bac3a2de637ab619bc0a1d307c4a97de7a84751bf7ec80c60168e6dac0b2493e674d12860a1db4fb25b69d00e5f4e83cc502770ad946b97828af4c01ff95e08dd788d7a7d7ec01a155ad382243ce49bb669e94761ebb8eaef91736d76373e93708c8af2caf2d85af3cd85787cd7572aaabba4bc7b447c4f85cc4637fd633e747eee41e06128b316ed1a3048cf96cf9abccba86c6f5d6b3a6689f8aa054dede32b69214ea6a107027f2caeee40d494a4e23a77e8d16f2f40935d5e799200c14b7a9729705c67e1844c5640e8e59207be2b9999fcdb27f3b2e9d9de1d5ce4e2822cd22721047ccd88d527bbd2120d5878190739a6be2b597b5e2a26270ebe74296611f67eb1e2a828455c9a3c9caa2edf63bb8090f7850cbd426a4a164b74a35829ec3669bb43c3c62c930337c66ee2c7c1894b7efb11ed70428cea4d14b03181bbda01da62674ce90a649b258e38e69f02d46a0008a70fa54234ddbb6ccd8d588e87441bf619689b120966f1ca0d34f303235cdc0f8a5c885fbce24bdf04d9468f259b45c5b06474f9369766bdffccad2f9a3ea5d4d9e62ad10fa4c85cddbcc204cc152b45d6e0dbe65599e288cb05ad5ca17c7f4b1061e3ef8b21ed762eb1ce8d635b12ed7c37b85d9f27f50a84ca643973322928d9f0a6f9f7dc556587830d6dcbc58ac6a2a21b1fdd290f3a4c16efc789075fde707726f6b3cec42291c7c8848539201fc5c2ce1d3a0e220507666f03bd51cf0fbf6391f8cae220278e8372a73007a3bf64087aedd394a47687114105550d76409a10160fe049e7d3bf0e38878a12d2fb3d204b48d440985d51a28784b45e20a4755da280453d5842b1cac1e1053f0f56d1591862341462d35133b75234684b442b2d399f81a44d8d11f7640cc412824b66ec460c42fca0018f7a63d7e9184f6377a8cc2618b9e5f02df25dc14b651a43b1b7243cc3898a941ac3b7967c32431f6d16d488bb9b5d758ccc74c6d790cad5a48186e30be37859759679de080509b5ed48991751b2e1e0783c2c4e6d1cc2681109d668ad84c99c522204c4c0cb79ea6e4a4f2b90667152953ee1f590c2e77688b2ca70c249b35ffff895aeff3c56ec73f821e8f91d8efa9ca0ceeda5e70517c5a094005a77b1b8d77d74852fe8a4d448a47810610741d9b380fa176b839f8eee3894bf8e625713158f5b9097ab5ec28c530cc0f18538dd72385a9d354b40bca3ecb8fc48f49c3656849fce65af8c04254080f5ea5ba9a9d81cb0a2685424d7bce4d6ab4a784276f00edb05528e6f038fd0a870f0ba0f4daa86a59324ea5573564050d820705f50f08c1199ec1035430c0607fb46cb3d801e591ca799e0a5e9166604f9f2a622a56c2768d0d441fa2ecfd1740aaf2f092b79928c7a8856a16f87fa6fd39a25b4b5023556febe42e571091fe4986a27a40e32d4ce639f3e24bd21f2cfd900328a62fa033d4d9d98da3411ac890bc5d7a2eff47043cf91c65013df3c09e322712b790a38f5ad90c1265eeb091c24990c66f2ad0106c06f2812bdd7b0912fc15f92f57b3f3103b313ab21f116d594f023a41c3f0f66ab265c763d0876203cbb61cf09546068d018943a7cc1c2f2fbe35f7fa3d64615ea3aa123749c36c347dfde9e1286382507a19b93bbdcb3b27f029cefca817a0d7109ebd61c300a12c8b845c9311d5f4740e2f1345f8c30b89b2c484c0e04386b81b2732615c4d0d00a1bbcc9fe75946527585136060e75e3cbef8f0cb89521a83920879629c6036e50d5cd1a7759e63dc26f8370dbc14b44ddad575dd3c1e9eaa2d1b5a4a789866330f3c529a7c1785aa2a54a5af8106d92027825c99b67da31b6084ab1968901863ad404ab347b7c1c40e6ab0810160beb01f0a0e5f0dafdd9431d1057e391a06fb21d5ad48dc3c1b95fb7ad70926a95e07efb741afd53445d7805a15e56c00c2df6940fa5cf234c02c787878a2decabd31d4bc4aab14db082940b9b362531a7f8502a2f96708737f053d9867cf608a04e5a55649781cd2cebeb0970c24994d147f101c1154a6e54a0f13758ad81a03dbdaf9ca9cb31e44cdb417d452342f7c9891564910090dd922b38d24f3529eaf6a3244a655be116674b2339f9d54d1069503cc695d9d3d19dfa040464aff7be0b83d03e358da4f26663a22d4c0737a7dd407ee88082b045bef5dd581381fc602598a687b51b836cef59ad2966bc648bf59511e5794915efb624f8b8f508d83af323b81b7b5492095a34e20ec6d4f5b10e55fa21d243d12fd449e51c695d4698ac950a4c530d21313ddd39b443ae8d9dafb0868bac2c49f6ad201cdc1b85e0e426f7829221804c3d3508830bd24b79e9a24316bfbd4ee72bf262aa3d821586b1291a67e1c8929741bc9aa8f57e5fcddeb44a3d829a51c37cbc8d727cbae727dfe0b1d3f954c09ac62fa30517500b7ffb69c789f9b5fcde086ba61addbe6d137dadcccd4c374a2e2dc3fa88c0d18b93b35f45d5bc7f01e3d7a00dfdc52728a67fc28125e9237cb6b1492fd676e220f1833c6db9812a94b46dd4660210fb59457dd269064e55410d1a87b05f37e19562c63a24a0a8593cf75fe6fe25a46a9d27852c57427996a51057d363d2d8dc34aa3db7aa25cf280b3c1943390fe1134341daedcce66e619ed3c1b491287aeb06a352e4b91042b2c70df7c12d9e0c17e3b516acb1c035dddb139ccfcb1d8ab8d09edaeca7125658cd49697c52da2944f30c642073135813c7b0c5cc4399ad5b91cdf249b48de6ee24c5b2286df01f5c8d407843926cbaaf9c2eb1f40a610fb20e19559917b944bee2b27940b8b4496a3bc51f641aefb2bedc7519be601aa01541892910fdc0b586151c54525903ad59b1120b31076785f22dd3a068df371b87e28b372bfd8b4e955d5db75cf6966e7d6541bc8a1525f34945de424df90465c1cd534d562d327112b8855924af13e1b5a86432bca06b7da982a726a8287c0779bc142c1788cef0116079da403f068c812eb85fa8a17e6d233ab572e7840a57100c988960334e498f0f33a931724fa1c3ad92434645db16831594a19681301ef0e57c0831f1b1712e09d36a80b730a8f34d0dc130200b1a0bf0643cc3a51e8cfdf2a645c65bc5aceec19c246f87bffc1853d5088d3309cef6ecbb07cbcba42e35a360684a2b38088ead13c329819f794587dc6093903f5d456b42499bdb2b824887c6243ad170576809159c8ef0abe8679b95e3847808bdd2c84ec9d45a44851b1d2b89997a72bc919a5d2e626e84c95abbd1c742664f60e10d01d2dff5ac87147588a8bf4dfed20d6251fbcc736b291c5f90cd47c514646ea3a05c6b26ad312f017de5da2db6c7035adeecc535b4cee510fab739bcfb861c38c583af694f4b5f14e2b695396451381c097f69787c4407a35ec9e9143538badd59dce7dccd28ffb904a3da6f64284f0c727c0973dc6a8bc86ef1bd35db106ad2056781884912a00cf49f081446598264a44269856837a1e8fa47b3d9fdafdf6c7e95e10ce421d187cfc9a2ba8f8308ee3e7e5ea3f5e3cce5597f209b20a71ea587d288a70047021a72c18e30fe28e83eb2b18af8fe0709da0ce8110d4ccb3de655a744dd67a3dfde6c407a6622774ecf4350585a1afa2c36a5428b5981c256eaa3cb257d63a562366fce70648850c6ae214251f2ca39e972f62f3dcccbacd1827e1516e5ab0ba8e2068e43d5415ad041637125a4989ffe92ee19191d8df7d214e70fb1a044553debe6c965e453ea9c8f3e515d8095a7553ff3315771396cd9077b8e6d3aa0706937d18b1c3b3a49f53ea019705e3f6609e75bf8701ce85798b541f33efa5c71659fb95ee6d5e47323f72c11b85f1b3c29cc3d1e6ec1a64b22b652bf072efbc21781758b3829418f7403a74a16601232554294f08d28f457fa6f7944ea7a02bd4abd0366524b60491958796eaa13726b428e2b5384cba838f1d9b7d5d295c7a948b23ace20f830ea0be80d0db2dcb5a7eed652399617c17a7026766f4124af87b03910b35f108be38af9e1c4e128422f65598705935110e5ea7180fbf90d7937236fec79a6b47b01d71c32fc1a1d7cd37f779a6386d2fe3c2477700d5c0b25b46d33563e10352190b3c397cdd66b4022782009da56b4ce2436d1591cab52e917566b60b77f03a5481dd0834710e556a1e9aca03ca4ae146956cd9d3a00c4d232e05689da16866ccb07a67761a004c2e34446848e4a83d9c5457141a926b4e0f19fedda76f4aeadb9cae1dba5e2d1cf89b6a78afab6d0e0cb758e906e65f8b563af220d90084efa380d13a11a769c941acd3646708e408656721336b7a25cffeb5f6d8f69300ec9f8d8a495042801e3aab28908090af92be9b30a6604996012f2bb1509d4cc2ac8ecc79f4050075610c8335c81501c9c127d6aeb18e3bf788148145e71b94d1bdef24848c29a75d086e458423f975e62fa9003f056caedc3b89cb81e4d0ef85d03829482d297f0772c6daaaad24c5026fec2d1b44aec8d463ec64d69a2fc972785a001056d373d105b5c75b28372813ba4553d0afd0419be2efb22cd159f13184feebcd962d86804246af0623a0e077573416d6c7eb1d8405b42314033d53da26009894207078104e1d0ebbdaff56f0b0a4d21c78d5cbf461d81558ba0a0e24c384e435ece0c8ec32172fcf11fcc82265b87291415406730f0784398d62814fc4d4103886cb0da6c1c540a0996b9fe98ef691c33e5ae821f831cdb1a7e3cdfb9e266af223ca274fdf91a2ae07c3dc97b687d4c044e2bd9fe0d92c0f4292cec563ee15eb3652ac8abaf93539069c15a0af3972aa62c07d1506394820bd23a90c03cfbd2cd92e58c6573c58be00bae61f87d286e9e8256e1f848340eae4b00dc65dc4222804e4eb2e0320b8a6ec1733c6169bcae817ac1422776caf4362cdccdbbe89009678e4ae8654a38e00bad5313c57ff45343c78abedbf89d34ae552c571087b7dfabe0194663d492e8ce07079afb95d055b8b5212bdb5b0594f4f6803336ad002f2716f7ae4e8d1cc5506d03b0aede789261d46afeb13d29a17b6d3c357c3965cc20aa041deeaee3ff448196bc7d8fb13737f455c1d55611aadc36b331f7a6eaeacfbf9cfc79ad4271bd8b776c77d64da6c413254431ffbbd13bfaaf4c90044d522cf464e112a8802a6224787cdded20a0cc4be8988110caca2e035a6eef292e03588667748ed51109e414e0500cd03fea5ed86bd3d7f04405eacf06d5aabc668bbf621ea3805b9e3a348b4704ff607d1561d8ae79eb3d64cd1104f3278b45602d298bb4b20d3f9aa2be6279132dcbb9d9dc041f1adb02bd1eb989e2d1d1af0a2a97725fc2987e4324b7e29a2e1ecdc00ddef09684ab16641b7e86f4acb22898e9c727ad8c380e95a0cff16a569f44101a1bfc11da743989bc9562eb8014428d25d288408a3191dccb96884b2df8aeb25a24b18f6650d7a4479c851caa068d112b17fc95169888b799434eef0d6220106298dde0ea1faf1c783b528351c0fd4558527e462462de6d615047f190876e75eca6fdb8c831ee0223aa47209a4de17ad5c62d0f703143a415175246de0e5314a2603ca61609e820144c986045ff4958e0226d934167441caf2c2829f2888fd6c249698c183140e665098abd992b3d408ae6d8f682d75b2ab5dd29356c6f8704950c40c3d28755f8b88172c5033602fd20cb7213f6b59f66c2dca0679ace056c97c43d1d0bfde34b3834ae9c2ce08e7e002a04b50415a31c48922550f8ae51d3ce07cabae6299570e0c25c75a0035645eac466482aae4d2e9870f6134ea4bfc9a1dbe69ed53c41f18ce99708ac86a93a65645afb266ce8943542a1614b400ba4bd1204dc8d0daaeee17217525e99a4e1dd77b7828024b7d68c175f395a38428238cc69b397074ec4496e77eded707761474fc7053528e88220be59be98e06a5d3461cab3eb8993d0c2ad7af8b32f8477e013f60751921aec08791ea002be6988e1c70b3b859ba8b217c80fefd8b405b9ed34163296fed2e4d8290820b5ca897e0ab924cb9e96d3021b718027a07147bef735a8c730fce123ba7c0313c419142052bd876d000e0d5a023ffe000d063ffd0720e2bd89dfa5a8bdfbf487056b8f740d27ab0d249c3f07639e0b6b9f16419097c310c67f814e91e1b3aa9313796706018f4b2b8c9817d570c179c020d1b39e8f31e30e4e85d6ad30c3f35347e2b4cb571b80419c00d5c235d7006d213c3e7a5ba3b756029d12c826488542973b80486eeb332580031d48bd4a1c58d1a5509abdf05d688960726d308e3d60841cf7462a5e1a3bec5e43126e6d2669ab5ee0f5db4deba6f20442105f4ceb10b8d4c0579e76e1e6b6892b94f0ee061037c22cbda418712f28a0bb18c227434c193d3eb3b6f920e5064a286627ff1efe179e95b9349acfc3b1b6ca75b4edf1860f0dbc7fa6e2d36e61efed198e9698dccb04c86264f2c151fb711f042a7adf7183e52fac72b7bbb11a0652432242e01bebd515aa1de22a855e12634af6c35f7ba8ec3a6e76d1e36a0a721081ecddd69de1de57bc53fa132afb3e40b51ef21b602ef19fa761a10b31417dc180adb6162bed736847f28168bbd88c62d848114f60261cb0685ec2cc7429225c6eb344eac657725e3a20096eab3e97699d8d502d98e0ae3e1fb82021f40f7b5f66ba17584eaed752e9385f39a2574eac35be5cefea0f0e5715785ef66b843fd92b92d8933409fa56ad8a0cf4b86469a69656c760be3942c7715e525ec415b62509d233ed8065d95ada59c29fa611f4405145d09c1afc938decb337f1ff69d5e32b3737de803bae45089c4a67d8e774b52f36cedcb5a350b03d6056d8a3bee4c6f080e8bcee2428fc7071410af8f48461aa0b0d703d6f81e5651f2734c6dbaa832be8b93edb759b75c2baa515587e85e4226da512c8c985edde1ad80df80a4e2ae06f64f4dd1f6b74294e8dfe7a9d0418e94c563a069171c878f20a229074fff937e8c23caea2eca678628bcb6305c93dc7d13a53509ab9e311e8680d30c7044e9e1b8ce3130d0ee2f8fd17903972cada6b2bc4ce38c71c5b523ad33b2be7081ee5d7e135255ad0df0999c344ed48ff936db3c0dfb456934c1d5a6e29d75b42aa41a31014d27a96478b86c7b61ce57ce96c8c7b7f56c7a51b4d8c12de3757e3d0a0a0a06d035dc7ae85d70568609d41a106bf7c3c39f7625fec5649bb6cf2c5cbeb28a3e4003b1f0f7a52d010a67861e6f0109f15ac6000ee2c9c1829c4d154a2940e904cd47d6d9ef785673d66998b3169e4b3368eeaac2165e14ebaa39e09277420c675afeddc48a9cfc4467598c04b018ac1b495a2a663ff77bef69fe5b26ca4124b79fbaff4a0fb343652ad7a074de3f3087b0a16be118d54077970bda2f65fabbd3b858daa7423cb8cf10931ba772d91f0fef2446f06ef96e956ee10d8bb56719a2bb17fc43881187bc121c5704455e9d69f9ed450096f224b49fa47572db647bf9334e67e02a672e0e95d75b83cfe41e33a0ded5840f7281a979c09fd7b014c120967df5dce2fd9f89ead00cd560edeb9ed7560799316ef8dd834bf1e9b1ca9e07a63d0ff102776da5b4710e64bb58e86c1d770acb5e01f366fc7acf8dbb833c9f5886af5afa05e8b86b7830132bb9a60a8391d4a153952a6a29bc919d4437d68ddfc87fac61b0a0617643bf34a81f1f69f70c7a069d848d7d14dbe8db56c90bac42455a59b760d2be4c51e78e03accdfe6564e7a52baf57e380d42a9fa2ff3690707217c902dcb1b7290e249fe9356e6bf8c7f1b4dfe129cfe06fe2101025086270e0848cab2ac6c157b17422f67b10c35f4085cafe22c321192b13459d9c9a77d6452f3c3e02dfa79f7bfc55576534bc140acf0a9f7ac5f9e1526991340c4c2718951a7e8fd164cc942ad13f8baeb5f3e22ac3543c82a7795154e5f82f947c6b0de6222f91c753e98c58bb70bdf2efb4b9b417a9806a805052cc19887a37fa16b35022fae35612c5ac1491248e822450c600ccab19d66ece94007061f54a9ca2a7583e5ace22f72b7210965267c65ebbe4bc793fd1d8b2601b51aa55bf4330248aed83ec14b4d1ef372be7ffb3a5ec64a092b84d75f20e13c47ffbb4c6e803fab2a8c6be362f641f12d67f2a0259f97269f914de1b9ef3fd6c16e69b61ec74e53e5073fe979530c20e1caf34f103dd9440ec6712141f63d9145a77e4ab5094b9cc0aa7e5828f3b27886197cdc3b9d0d06b2a61cfcc0783d7667568165b3a0e4f0dcfbfabae2f55d6570e18859d5adecc49cdf6ba180bf42a718b0bf454adad5d636e74e4f3a9627a313b2ac638bc1cfc3371241a57d2808df41b8a8ae89ca3706f7e7092f7c7b759433baab573c52657577d38c2bd31e1b0dfa0389febff1a3529b00be3c5385512367345f6b270b267b8fda77d1d381dfe2bbb082f08f09df6bd4be0f8c7127b057b7e75fce9333016d204f3af907062948686d05a70263a55dfbf3ad709334e2b37bf253e3cb4dc0e05c49065615138ac9b9da2d652055fe0e5b88670b440cdb6003dd5109343828cb3f82fc47b2a8b72b635477e4663ade3afe287f6faeaf91bd6947db5c76d494997170cc44a51e211f57426b19813032846ebd672dcbf501a3a3421f0773df0caf7a142e215dc91e600cec48903a9742e6ca038b5aeba21b0715eff7900c0be6a6399412d252d83643b955b0b2821a209c16f7e5aa735b60de1dfd3e0c86d726d16759fbac4ee26b015b69d7ce9f9687b52b1f4aea6d5bef6ad3f3c8e4925ccea84105fe48be87e21e890244495d1c24fe3f8124f27ee093811dd0189890f383252f59221a2ce64b12c204cf63380e05499123d66e01b55320f7ee5e77a1efc5e87a662f6fa9bf476677897d4233f745856b94b6f3d0435f2cb013ebca3feaf33095ccc101479cfd6a6743ce1c7cc0a09e76eac97885d3cb8d14150d3c7f5d248ee17f5020e8f249bb795dfdb1da17c5fdbf9d7bd2a4b1c55f0691fae3f113552e106440d3f1f249bfbd452f9022e396438812f52726d885a7a1b35b5130d3a97554863c01af05c123ea806a11100be798ae28e0a0580d09be36dec2c827f7f74a3fc733c7ea5449750d64be3811eb11662a768a6ddacd2ce29be9c2b493bcf5bbc4c6df254c799546770970893f945e4a779988a751d1128019a7255265676177a0eebcd3e6a133a14ba7d32b566d7bac58d58963d575492b1c9787741f3ce5de6ac1a898791516f44ff1a486edd1340dba825b43b71772afb34258330a38645db3f9f66a939043811bb9e895ffbb781a540ee7ae28125b0226bfe9cfd2e42a7646d727987a329b4ddd53a426218a87a287b4955989d51983c3ece278c98d292b7e584a08205c8116befad7adf8f58b459c666f10b0223ee2c743db325a0c7fa422cc9ae732d932a8978cf479a460f38fd7976978c5cf09f20d815a2c2f53b1ac0233e691b338a4419a61f3959deef6c050709753f543c5838d43157c8efc44747b0055e2d1571a3e67145d8f48aa33c0cb4fdf0bc936a3daf096edd3f818bc13b7d1466df4f2f74f4b2453fb15a8d3ad5a6747c51d5869edce34f57ef9f2de5a2866b6a23d20db2c6364f2f3d66aeef381fa8edf4a84cb36d25a6c0edd6260074c791c69f2268ac82b23614ef157734f7fb58e93b48acf3246f67257cb1abe4c9392d3977a3eef903ee24c14f395aa67469c88c4d43863bd67b9b713b1a46476002059b8dbf2775cc8a533fefc4e56f3992bba84e2dbaaef3ac569739fe1b7c3d578a195297d0526d4c494c8924c69150f4f452829a4cb29be2c8934e84ea1877c9b30fa4a20990cf03c712dd81595a2ea8a831bac924d75deacad4770a57c06a10dffba4312d00f210b00f33d9686a25581f9fa413bda4f6d424f6e5b92cf3af6d23e6cc1a0f2e3d3dc3412d83cdbc227e3b72746956deba61f0e6e07580c10c87b193e484bbb5a3fc40032f1db8c894943673150ce6a9a534006a283e7e26f2f19e17a49011c2bc8719f97d4323e69edf86e76eb924078ff9f4b3b139b310b0301128d443294e61a19fabbb620f4a28e9fae1c8108697a299780a195e89436c8268c6160135eb443f949e57f47126f1356af4543a6c4af1c7d003e09215082a69fe7efd2fd7ebacd73ae29d6ef491765707402c6c596ecda3bb0f507043fbc58f779a4e130740ce21ebed33fb999f74fe43f796ff91fb5cec3b204c0c476419824ee93881504ef7f0241f24ff3d62231cfa16df2064a869a047e5f276a65ac2fb6062a5d2bbc85de6c660522b03395ed248cbbd21d8c8b91927519379ed2c2980ada70da1103e39ade95eebb0bd7b705fc797ac3ff84f7e12d97c4057790e30c4cc816cb644364da881a3aebf7f38721ab97c78617fb03c2bc837a92b82206a86898ec688a19bcc6a6d5002a7dec897b093b040f6c7e1e38314e195670cc68049a5247a5532020554d070f9917d3b0900d3a38dcf434f82a56650c6ec2cb7a05bfc2ab588d8ee6719d50a0ecc3d0595c806442150d4500455b04e563eabf2cc138c27beb47704bce05963aac9b9088edde64cbbdb74c29a50c0a270a2a0ae01d261fe1b1c8dfbabdd7a9ee4f70a4f6bf88695511d3b73753faef54f78524d37f8faa62929ef44c4d1fa97b333c4b3748cf1fbfe8e120919ebd195273945fcc5ce86df47b5e12353e8f7864e2d12ed21654f46644df89284fbed1bd67dd671da33c8655ddf7a25fb80f743b8051f46a1e30c41881762a3fbf62f42f64983fb7dcf9eb96cbccc51c76fd143312973dc6c8404e70fcc7f4971bf1e5d929226c6cb90f5f798e03cd56f19030c68060f115c622b56db267d4fc9cda401e3357e42b56f7b90fc7e1be8366033d6f1007794cfb788ec60a62c226a49dbaaeebba6edb847071b5415304f5cb9745973ef9c3c95f3b4bcb80ccb0811aa8a990a2d6e6265ec02902852549eac2a12e14ae70439dae9e6fb55ea0884424d42de12fd363b6974438ef81601836452b49eb48eded96f018cec9015ac263a4c633639fbd336b0229210973cb6348def257f566ebc5b056968db468323271d133f53c59dd3591d77d1c44aa42a1f99c3547b7204c49bd14ccedd94342fbedb36195f6fdec8f7d5a7647ba1e1ccfe019fcde1126ff2e8c1044828aa124a273ff6da32b3796524a96ee22df6770e5e4b8557ba2db04cc8d42097cea1225956140dcf388ccf045136816ee57254344baefd721e3318ca2622a69968c79e59511703af68567651b2b63d7c6aedebe905fb599d5db36a3369a232d6ed47ba6eeb27647cf6320fd22451fb3b620cc10f552a0929f7d9ca88769edfb4299dadff139e61d0a0de1043d5cb20e7e7f607ede658850c710fd06b97f146a4ece24147ab053a110c771dcf70d822e9f4b8882265b88820d6ebf45567d832e0dc6005285928867dadbe8d5d129c263e8bef4777fa8bf880eadf7d1090f819692ca7de1fa14b13a600d3dd310ac2c43ce318d51d66e89809675cb3894f9cde3d6016d5fbb36daafedc3766d5fbf86ecf26e7581204fed7fe11a62a42e7dd12f0d36b8656ba3332ac4bf93c30c4116edb761a0c3bc34143304b78f5d6e98212865bb24832d1bfc5f09bb674a9cb01ba73d18ccd05f0da3e167d958b800feb1f007bee89757ab478dbfaf650d8b5f8872314b94fc98878830d7c54f787a907491adb74d6b948e82c8aa7677ac7bd336cb32ef6edfac59aa6f9702c75f3c36b38de331994bdb7601093181b50560cdce60b54d30a4f69f584086d496daaf0989df2c8f8940356c57b3fc2573491bccaf5b5d0f6628398bf90d3b27846e535347868adadf02be70218271785884c45f953f472ae9ec6e9e6e65a08a08875e46cac0c070dedb0723c3d12160b2e7be2162883fc2c834c8bf655cc4d6ece311ab1260fd58b297bfaa4859b2df5e561ba72e14e23a44124a1021c3d3334588db50de26251da25f1ac60833fcda9f8865f58e6121055848413de1c48d0c605df00511a2ac5567cce83759753b854f9246d23c512ec82f9a3061c031802d77430936ba9c9e7855745ec37c54836760264c76958055fb452c204398550525af5a63b80d40413ab55640418fdabf456a730b169382975d9d622270bf8070ab7138ba228e9760bdfaa1b76c50db61a082dadf48d8981459c32ec27de838281f76134ebabb0ba50f5b0c61a3a176bba1a67ccc8445f9764fbedd976e4ddfd7d2b7fb6222f76524eb7ced0b6596f01866ed4b7ff6012d2afec6ce504366311376891e503e87dadc86da67a81d86dacf5ca8bd13bed49502dd19fb92feb033f60b1f50f99740b906144a20ac40e5f066bbd94263e8363541908adaff628819ca0ac2f40c104604bed8bec04149622dbe2d9a0d6a289821aa36cabff207e936354d0b54fb99b273c7a21d62762b9ab1739f329376fca7ddd089eadbe9f9d475bfb1cc6758e59f6aa3bb6d3ed36ddbba6d7b53a76f6f8a23d2fbc7a6e5dd988abe5da3697870dd254b96ca06d7c44d5f57235317a69ad6ddc46caa2758e814eaa0e83aca452214dde9449d610d9ebc3b7d4743f34754fb13d5b4cd6a62d5321655df5f1f23de0d193a4d77ca1dd38e9ee81772e593ff49a66ebf7d5fc8937a220f87e8e7c6b04e6d33eccd6c3a4c5dd775a64de93a93c9480d573e05657a2731ea53f9c2763699ba9ae60f4d349c754d6e6c9c60a2ae09bf2f1fa921afe96918bb35f993e9a3e9a277c4fa9bfca9f45f8c0e5979f4fc752ba523b3f4d5741d7d34dd934c1fac9abc09e964f2ae83fdf7631aae7ca68fc59484c7a04e72ecf311fb27aec1efdf89554e230f8793dec43b624f2b2a9f7baef2225ff9462aa79fda752613ddda755dd799481f176119268fa2a54fa1a7b7e12291890e8f41f192f018940f75f2f1ee7abfbf9fbfe9f7c31a28b886c9e93fffd2b349e9c3385ae78f85f4a737d13e86624d7faae9ca7938f6694c5fc8d23b425417a6149aec177ee074fa923773ea3cd3dc6325959e6b28f3db33145c83ebf6dbef5c9109ac8626edcd8cbe8ba7d3e971747f4a4254f7444b262e7d0c05cb3079120d5dc217d564be09ddbe2389d88355189850c261f267a2b5d1996f9fc157f001919ce09bce5eba80fa51fb5ba22f51f7799335b1b234c1e4ef59f8290b7fa896124c9c19825993a1dbd49c3b3838b5dfc6f130fb9932e156b03361c37e87b90bf60952565da43d88c88fccaf71675fd6262ce98847a39da46a3d9d0a63e566a6dc136b36e219f5742afbb20f7d28a5ccbe10a5c30c473ca39e2cfb11cfa80749186d748f114fcfe89e9e31e2192119f574deb176ad4e852939231fc95252fb258f0c524753743ffa96a2323792cabdec24753495cc118ed3dbe8235d0c37190a49132d0129b54a41b82943db111cdb4fba854cbcaa121bcfa9753ae63d6ff49ec97b5908a8bec7344ca571345ddbb22dd39eb5eca3e93efbd026bd7a1425135a1ad220cf0849835b1df1b056581add06c3510f7521f13b1a86b8286bf4118f9423241367fa182581192919f58c804641b307cb4da3ed74eb0849bf348f19a6a8c18c872743e23d1aec55e13015a60c254bb25c3af52e5e1f24d450be58ccaafdcebf1aa9a0a0dbd4445253de45fac886c425e480e813af921f5f30f72565bae9d061869b4e4452fb5932c71e8f91df1f91642d8f91df96e5643831288c40f127fa8890b8ba24afd014304e496ca3e2e3a98d64f7db7460fd8a62ee87fd0ab2e9642d57129f2994d4feedd9a4d878369d06bf5d10a8ae0f4e64375a6b4ff08f74a59cbb34b69d93d0451c4c397d3c674823692974fa08c71aecf7e9b3f21f749b9a53ca25416abf686331a2406698ca8caacdea7acc1b5bdd5f97c79e4e6dcc820167ad50e4e5ab233ad1c70a3658420d9d27f424cebeea54e8413a288803e9a0a0fddaa7c1f67430d7ec192736c82b66c6c93204741143987ce10b17f961cb6975bae73e9c329c214c7597c7745f484a6e4ef96dbbda5d20cc6badb0a447edf7219d72eec13fe20b668f4eed8bba257417ce103574d7907e69171066b83afd2e3b15c6d0a6f2771108d80f48bb891e3a43b7a919ae0fb3ae00126439a3e1cc36fffd98d560ebe35683e0766f6fbfd62233cc90593c9b2db38030334fa78a0024083f2a0f7cc83951a877906db03df687590b0309f7304f83fb217752ce8962960f08fa641e336d0b28293f69f7265ae24227822a4dca9fbe237933a55228e4751d57a2b276271a2ac13995fb14cd85a2831bf829b031dc6a024b4388e71e182d8055f885026a0013003c837de90f555ed08de95efed2317205e379f4fcccbdd6d2b8d7827c9a0b063df9190259b957f742fd83204c4c4c6d791ed5960f47358c722567b0319a15fbb2e256dc0a0d35855b69d3512c58b0f8ca22e559bc10f4020b23e5d70bf298b8c2c0bea47c36b5202b5074a829ff72434df950dae89794ef8fab944ff994cfbe109592f2fcf5a0529ea7a55f529ea3b2c1943fa1a20653527e44510da6fc7a0b48896dc21da119fddc5e1705b15fe844500d471f83a034fb28df71c7d1d2334fe650ce93f96529252e854e04d551fc142a2b0701ed998ebe9073eac7a5289fe570f3512697f241d0ad994909cea9282ff28ad88af2eecda03cf7edfb4dd5e80b0d65ddefe5334a83f236fc85aaa050ae20e5c12e280f0622f443c825e4030d4f1f0d6568f73af5c0adc215431452fb5b68186a42ed67a1a10a898a7e856a3fb45583dc6fcdd6c99a0dc7fe8ed1aec692158572d5569e8e6ddb5ed2d81a7f97ac6c75e39c0ac481702b204c7d4543af06d945ccb9e07933aba5112ad2291e35b2927e72a1d7865e1d89f2884ffaee46d7cc3a43afd0ab53d993be3f04ebd4e8491989f45946b776af8c72ada4f9a4b07b4d1a990221a9bad309b75a18dc8ae3569d8a518a8e018122903824b2e22bc2e211eed52958f7e256a157a7160a2a98a2f6878a744aa676acefac987de835c68f9be23ebecc3e8e7cc58339fa1fa7e72fa33c6a506296f2dd9665a48803a619e94ffae4249e707fb27f12ffe424f4229932d2330de58f4e3eec5ed1062b03e579d4c83a69fcd162e1a0f6471bac8ce6c88a2ba0597a141a461cc420a4afc49af1475c4dff30ae22d72642fca7d32648b0fd13acdabeeb0c30fa6d9cca6c0386810a4ad0a4f9cb91b8ca71b5227d7135bfb8e26214a954d1875c153d6f8cc98b44af859e7718c0c45de7e108c9dad1655100abb6a71122021b56e588c0ff46b5b1ca95bd08b0c806fdb3b9516db1155d71c571abee55c3d00be4be38e330435fc5d50f49e3ca5f58d1b50a43afeed5bd8e1459fd88418cd48e41ea2e6186dd2bc6968812bd9cc86e5c9ce89be884dfb4137cc35c0678d02def33476fae3796d90ea21ef13387f58cfe8cba4e8b1769b095b7d12a1fee6f1f7537e2308fad7c6ec4619cb33d1ce631d80c1de6316f056664c56346b61e69dab1061de654748c8b981fe11c47e231ef711f5792d331f631d3afa5e1b58f744c0f95eff184549d605bb264898ac826f7632bbc42b9aaa8709d0d72ce7442cd565bd090abca2f5581c160b0ce615e39d2c63e1a6c87756f1fe7f00ae5f960869ca3229fa9a8c5ca17d66cf2b59aac8666b784fc084152bb2d6246d922e4fb516e4af4dbefe7ea16f3b6adb8145288f5a4628a422f0a6bb66e752baba675ab532a2ff266543e9efbd56c55f4d2c321fa1da3254b9654510761d187de468b3e141abd8d36791b0de39c57ed671f0e73232e45b71646bf0a8bca77a3ab4aac8ff8d4fe06ea2a3a0604da28bcc0f34aa2e3d33c517841490dfbc7e415c5174a50c3a6a2975b43b8430d45d19ba99931f96ea3bb946b7763e2c8ea7ed727f46452f9d02b33b3cab3e94fdf9968bb4eb45b26930abfcaaaec7aa86e61f181c9dfb5b060c1e27977ec872b2abfd252a4597c6d640e336c9a1dcb62e3aa42bb6e741d0a2b63e5db4302f5d967c312faec59f5df7dffca330a35a17c7fc75ca5c5ffa2fcc97727f4f4758bb64b0713e571a050d17ba3ab0ae943ce7128ac8c7e15eab185d1df82ba4ee9db7318d08c0a587f096b62143dcdcab30d4be833627b9a7d03d426b2ef09223b0c50b76f15ab5e25cb3e11645148fcfd8490a089ff2654ebe9c844907d36adfadf72ac3c8bcfbc23569ebf85360cf5ff2dffead4cab743f4853795c5876fc3b7b7d12cefde0cddd1abfc0d26aae899ee0885be6e69e85950f9dbe2c316dfb1e85b6c1f4df7a16fd17d34db6f4984e26d83fdead4f6296e2339b6e76f415b3e37e2f5f02d1cd603ad89755b6c27e587688dfcd0bea42c3e9ad0ef4bf68ee85e7e2c21d04078137af9852c39e4772f3f107815fd4d0d7d21d71da1a7d99e778468b615965fcae25bd096aff1badf995a46cce2471e0e162c9ec517020d7c21f0ca7f536d740b95b56b4f01a85f8fbf90896e446956bec69fc3a162fa9157c45615fef55468547ef4ece550f9d177eb4100f52b5f285b341aad3cf72c7fe2cdb07c3c57be1aafa32779456c1d7db78946a3bfa9a1ca6f2a4c54144da129bf519ad16fb5e1363a857aa3ad2754d61395251aba1426ab7f489a19a3a7230b2d8055f16b8204da3fc12a2d7bee396f86a3b24e117b46b4964696d51cd86a61b0f0049ad96783821bd508b26f8204d93fc1aaecb36195bf0e87ce036386bd4859f9b778c31a68a4072b7ea4f1935b056068f5df50a80761fc43d0ff05f74e61b687d9603816219c90a8c96c19b8314501992128f3851b0379fcf34c9bc116e58c19abc115ab53f1b90fe3675faf1a6cd68f5ec5af599ca4614dacfb5baf1a64ad5859dc9ac5b27db3f2c86a4dacfb752b1c1c1c1e788ffbf80fd0f3d01d18b00116d37939abe5f25590e300f5f8fcf0c0264afba8bd48fb621a669681d363a26a86200fae61af3ab55a18fd33f4a0a04e7115deea81b3fa11a4ba08f1af7ff44bafe4bb8c6ae05aa6b97377777f2ed8dd3dbef6a1f4d72216a2c899793fd0f7a717a67f7fa4720baed3a9d05b3b279822dc8f38ae841fd5e0a31ee53154cb6ffe853fd4ed6d348f19ed395ab7ddfd8dd66ddb3629a5dcb867dbb6cdb76d0b7da13fc3dcdd99b56ddb16d4a150e80b65b83d95caaf4352f4399012ffd91ee9337f620c6302c533755a31d4ab25717c2020237de64f0c08c51392feaca4c1b9ef312977bf1fe6fa0b4be8f39f06fb678ae985c92f3ff49fd4722dcfc35e9152eec0800d65a8a1b772908632d4d0715850852800d5b07dc28e918accd063dde223ccd063b14eeda7f8754a56981b3d06ac2acbb83ae51a85645f4bbf444f9acccf3f9c0dc508dd0e31b96e655d12ec8a3146eee3968b83b41a7435d8dcf26767efeb3efa4f9ac447cad5a3e10d8a23c9ad8beeee9d4713496622aeeb54fc85877a984e914894c3256a0da9c58ae9597c0fdc73cfd4637c9612c7e7a8f61e0d93a85ee43ccee33c2e935f9844e5dfbef8fc5ee65ae65ce69e7beeb99771fc9e995efbcc2bc27bee2b59e184a31ac751cd145f8b9ce9b98fc6146b32d3bbe87ba0ee19d17dfcf672b07cdb608b8f5fc8e28b0dae7c2aa527914a247752e492ca775a54696979959616f005ea3ffb8e518f329124b7bc67eaebb1fa7ee9b9b5c58ff4f927b9b5a15ef4cc6599473772317a0f2d5ab060d1d2c2c2b2b2a2a28242a5a4a0a09c9c9c4e2653a94422cd391a9998789e48d475a110579dab6c924fa292f4e1565d9abec4e2aff22b2aa4d2478241fadcfd0bb5173dbff45e94c4163feb3e8b9fb9c718a3c6d12cd230f3e73c46777fcfb54f792f13bd96c5177de10d9775a247a1204cbbbb7b394ede7b3ed2a9ad4fa97f7ca4c17e9aee5bd8c806d5303394f1a67b0bb9b53e49a0c0a7f65f4009bf7468bfbf95a5bfac60720fe6f75f97ae065bebde8c47af88966b3fc669b00133e45538f99f5b31098ee2064a604ec2677e3eb1b53c608184d3dd7e21b83438ec77fee8523746f359fbfb63834c636a8bfeadd1fefae317bbdb9fd73bc624cd53c14f482cd260fc64fca51f02f16362098f7116c6fc42fe616bf00f96d1efa2f287a8cadef3c7e777591a1958e7cb1861ce0f652a116fa3f907d76016cbe847a1a78f218f320c8532cbc48433200bc0c1d97d2d16c1bf335a8ccf2a474083ab53c42bacf168dc9745804d0d7db72637ed594a4f7a9682a5f4dde85ad2264fd1cf4a7690a0e3259246b736acf68be94f34d4def4ede598256a1a7933bb914c2413c944229948a48f5ae94da56f87674fc31b1d0d22a0c12296f763d7f3ab7b9e94eb880af1de4633904e71ef1f2a7eeb2f19f73244741fba70e9b234f845ffc3d66818cbe817bda8615ca36345c460ff6d9ffc4851609828368162ebc474b8081fa9c28655ce35b80b2ba3fff58528d47ed4eba580f8ee3191eb02fcb3e18f912c991188ef0e68f9f7f7c380277e1af785bf534d68c3a3b176f281cb635ab52ee2d6afe837d64e89e63af72b915522cafbb27d47b72779a06acf955b157fe10d8c4de321dd84d7e4185bb617a1811a08054d850bbf7a066c07443ec0953fe49791067b36900cc20cf9d540af560df9557bfc253643294519c0909a3daae0384967cfe817edcc184309c4ffc46a1f4cc8eceb9c55cfe88f5fe7744eaf803a26aa4e35445567209a19b4384c26fca53f8815c484c7b00ddc8398f0985555ce0962669e2930a106524661e401919830b9771cdeeec1435d1d29303c303c309c89642a752794eb76cfc2d876db18043aa2c393644382a77b5c93f138a28d259980cbba549f4c74d26d1be4ae4ef1d0643cb75cde8289f1a117d99a5b1cbbb897c13d0cf731380e4757ed6b9f939347a2410834d8edd33dddd3499647c7d238c9b22c3b59185fe884e32c0d961ff6503777d76fde0dd77e4f4c770235e45e09977ad2430dddb53c27bc46b66d63ccf96bb7507b6be86019bdb9cb6374708d7d7f9d9c8a780b1d37e28d97933488d21edb9497de8cbca13265fc7a3332fce473d7c6e01e9f9e243e30bf51197fc24131fe24c6cbf8edbb2ec693626c313cc8637a15b49a1af5da434ebeee24edd33d0ba387746a07c71e4abe10c9ec3dca0bc4102068bf38175f17c9c30cdbe582e5b7ceecc32fe5aa511914090a8109b0b0b020d13d8e8387eeb161d9ff4d0443e5cba0d9cf3bccb05ddd33c56aa5575c4fa716dfb9c807bad57bf8e9fb7da0252bccd3fbf02f2f1fcfd3cbc987f5388a1c6769f8f0dda2458b163d7c7f7261f0875c4f4ed62b7b3850fec4362cfb36372aef9bf09e55937b9a134ffb562d3542f39ea910934f049e8967f23b3d11789f4dabe6ec249dca5e2e0d7fe920bab2f8ed1acde235faa21b09d7e0efff76b878d92f92ce465281b8b1fd09fde1d79bf9817f97e376992a0153690760ea7e344cbf67fa3dca773b95d0f77df766e8bb12ca3f0dbad453c63e643c6aa6bb4cbeb92fa7efef74e29571fa8dc6054f9f51b9e0e97da0a2054fa7d1f6236f665b1a1b3cfdc9e69d4e5f08b23b4b6855981bc9bc1bdfefa7d18d73a9cca7caff62be04e1c3875d0dc7e164f6e1944ba3e3a810ef8286db7320f81d8b5c7cc83d78f2d1b878211e7c8e2a01534f7ebd1c2e3e9a93e71e252a7927bf7d2704e50729101f129e0e180fbe10ff020605b9175488c90b918313c205f7cc3d0bf12c04334b0e7e215e880ec0d450fbef6f2ab783694ede85d3417cebeaeabe0f5fd8525417f442987675eae48170f12e1ea440fc09cdbe8eda8dbc1920803839f15cb80082cabaace4a31fff6c5ef6ec33e9d6d0b13eb84817cd87df3d79cea7410a700f27f181fa6b7473a12170494d85b5ec930d52ca943e0779cc3a059ab443984a7f3d058c7efd857efcd360f3c734fbdb6aa387099aa1bbdce5437639f6ff4c431d55fb18e64f53fe444d3dd0b087dae2e3c135749c9e9e9e30e5bb16754fa7b86da91d339f8b1de3bdf072cffc859c4735976a42519682b24e0f27e914ef56141a2ae1d2496f8633d94cf69927569a69f221ebe8f0dee46b8204a27f8255a28719e998e97d1324f0fe0956799f0dab449b3a6d4a48ce322182dd205601c3a0dbd8ead425c00c183fb8f809ccfab6ed899f7cdcf769347c976af24c26a69169bec9a4fd88be0935fd46bbde6d3717151152ac25d22724f430303030757ecfcfbd4f44fd45dde52ffec27d1080e998a2f623e11ae24692d4969911f9650eeb1e21f1f321ee3a7a92bc13db4de604df74764306fd4e8249ee7efe68826ec6b97fea985367de4c87ea4ee4a166bb61c6f75ef435894d14e9a9c1f6e819f1f3840a7dd1dbabc98cd8b6cc9790eee59075934cd4f8fee2d2398b66e8fc494c98fcdde42ba4d47ed6bcdddf290a858a84602166c3dc28be40458d1d176ad0601ecc83eb8c18560ca7d39c0b7096bf844e040e1cbe7a203cb8af46d6adf1349eb91f1c270252f96bd0b8203f0d2a1764223e8ec5b5b9cb44bb33aee6ca09d2a2b7cfb13816b7e2563fbc66e39ca8bbe443afa5c171619cfc351b29d4bd96d5a9fdd1292ec8ee8b0e2f37506063422f9fc0d298bfabd392e264b060bf4ce7598a5b2d7fa4ac7b7548e064b0a94ef182a4efb8f218997d2191b8ddee15e23694cd160a89a2be431982e55f1e8506f1d29b91decc4aa9e3becb9693d9ddadf11c652208f05c0f223406f01a0ab73cb3d109112f8fd958acd7b6c1361f7fe947cdc9c37dbef96841bcbcf28ce878254747dc277b7c12a7c167d9a3d4a3c1ceba4ffab0c30c25ce560250918f85d14f29a5ddab2bd2c13a235decf3e1fbbecf071f7c40427baf0733e4563d9861e865c3c2af23a4e52202504ec9c2d858bf2d58db82b52d58b59f08caad2847837203a09c0ce55ab0efdf7cfe1f357b80a15073fee6534f384972a1e282f42ebe7311899ef8581a1beb14ca0ff2875f8f11c087a8fac3d71f86f850bafc6e4cea43547571f9182ae32fa44fd1dd971974f76508bafb62a202a0eb26d43714202610bf1d03c49b782e7be2a29377f1fdc98571f221d7399f93de11f3bbdfbe44654e83a83ef94a6fc3c26f73a3f26fc29f55327b9af9dce85bc5d488d1d3f01ba03efb2702df7c7b96fe22f0cfa655f2dd5380f6127c6eb534f6fb479473a45c18fc92965ee2746a7e3bb26ec4fde8b56e13a1d020de09ce5111d9ef7c832da9fc4d6c8d0db632fa399b24ae2f383a1724bd66c5927e5f48bc3248304859c63df727134f833164fa85f4b14a223d00be70925ec647fa189f1674fa4269e2b4977fe18aa1925048ff227d467aee3bf9c275c31c7da40f517436487a8d927ea3a417629354d293bc257dc741d0adde0dd4934e9ea33b38676569a07cf685dda431bea3d977f3b9f9a6ef58d47d38dff4a112bc8af1a69f54095ed5d1e8e773ef7933fd1247f6e814f7fd32a753a5ef46cf7d1783666fa2a5af2bd2bd60def4315ec6871d0c15324d530615b27d8c6dfe9c9fd1eed7cb3e9af9d9fc2cc66731b26c7ef6852c39b28ff131be0e704e3df99b3ab3df917d3423cdbbd1353160bc1002e6057401c40f303e7cf47b8061d1c2b2a2928272723291be10668e4c44ee5191e7799ef7de7b5fc855761d982cc3c970329c0c27c371cd35d75c73cd611cc8811cc8815cca3951a87f18ee4318e79c73ce39e7421ef290873ce421ae8aa8a4a18c05bd7e5a3d00889104cd0b5524e96ef79d2aaa8872e8a1058b16961515540acac969fb82a9449a23134fd4853899c960d7d9d77d30f963344214b2c556b8d88a236c5618893166991553d8b64dca2aa60889985a61854d075de90b6c451cda0a2595995ab186da1faf3081ffc86070c50a321a6c40f28a233b57c44e57bc7c50510d32bd024977bb57a12486c49079335996699a1da8b8420d524ac985ec70e48a39b8bceece92202851094c827a308aa3098c979720a9bb73c590ea2f5af263490baacb9228462213131393d128e8c7922976a4047987cca7874707862373e60ac562b9608240a0ff41f9cc1ec923512a56edeeeeca44aaa99678e1e4ac58ae48a38a7d6238392b56cbe531296a1e1e9ee6e1e9d63269927d4222cb20e9d685880fe5a4113e5863be7be48caf1a0880efd6d210c1cced41219e7f9686f7fc830442ba90a07c9141c8d7caa81cf8954355cee5e7f9b5344c9e9f89a53152f950460d3daa45b77e37940156120ac949245949a4b7b134e647d3f3cb8d71c94d124a657d45e344ce1a5f385134be1035802f94f962644c94a92f9473c6174ed40be0db58006200884598bff44b982f9432626c108c0d7ab141427ca10ca0205e2f2ff0e5e205c4eb879774f942f9f10fe51f17ffb864d4907f6a26e5ec164bb7321f30f391d1230304b547cda9bdaf4abe2af9aae4ab92af4a1fcad854251a3a0c2abfeb4839270ae5ff2158bb2fd14cd3344dd3342dc2b62dc2b608db226c8bb02dc2b60f6554ef4b748b40deef3202c9082423908c403202d593cc5c2ee59c28d4bf8320f7a10c2ef391210304ffb3d74a34a4b148a427692c92c622692c92c622692c7fae9ea8a94449df1c99bc7eeac2e8684fd4786464ac610b82bc03338b212868bfe33823b73d1c5cd77dbff8a26ee6cdec977938b86a51d3bc594bd2c9616eaa7596b7dce52ee32ffd2303241324e33839a1af966857bf60311d9e05ea71f90b90e4a08983caf915c8f2f117988c4d1d14cff7803e3f302fd0f52d146bae5c47f2cc1e94cfff8040cd130403ca3c8ce778cc3ccbda3bef31fb572c56abe572bd5e30e7ddddc5c1c9f11c5fb55caed70b068bc574ea2e4ffd01aabb38383939ab15ab6eb760b1babbbbbcbbbbbbbbb14caa647ca44ccb043d8e4cf55066532dd1adb8409a8a5d1e032483260e2ae757202b73652af681c9d8d441f13cb38fc63e51d52c1c99335728d6b740766da28c86cd7255f378ccbabfe7788cf4177e20981fd0e77b503c3ccd33256a3e0a7c1870fb84689fe754ff4859b52efed1788c01f082e56a6cfe4e661f659422cf1606ff7e2491502defe25c8ceed1b9d09471eb8b0ac3ecde7945c48fc3185a24b0bc2006464043112b6a00c50aea9095606ed46cac4e04aba6a9b42cca0124f1c28f2d7841481674a0729c37b09c088f20faa7c75605151c90ca062ad890873dc06f1a5351e39665191bf250638c318ba5ba3b6d48410de7d360c62d5b1fd8810d5a8859ccb6cc056ab0c2146750e2c3057d831ba8600dab36e8b040e3c2136040838f36c4616b8315394a509082795ac3131b50d7e9685c00031a76da10879d3658a1040515d520a3a153e2030523aeee8e921b34b81cf098ddf86d8cbedb35007450ecedaedce9f16d0f9858d9610c447070852ac061c95aa0dbbaa2a5c15f6335049ae7d5f3a9211099c4ea894c42a0d5a5c183816a084a7569f0609cbac3009571188a2efecaeeae02fa65f6903da3fb25bca95b80b963052950639082e5f7b7c8c9cc4be8b86e84c9224fd564b66daf713b6e7041a66d9aa66932dba488d909954529703166515342286a530bc206318b590683ae6adacece1aaa96c57709d5ddd9f951c387d9bc23749203ddd2154ce1609d22f6aeb8817de1053039cc400d53b040b51c49d460016608d69789b10048ed7f414415452be4f21763818f1a3f5483fe82ee65f620e23b78495ddab9efc685b16959f4fec13df8d19d85ae658354143373bba85347f6338122c6e8ade75f14486aa9ee4e1453545434c2280a1ed3809d27a4608312e401097850c52a6a381b02290842b48a3dd1821630a1053c4148c20f78640c130b55abbb3305253544b905726e5610873ac47640842270210f47a230a9bb73e4453f6a9b1670104f4572b02305978f7912d5dd89021d6a383f8b3ea4ac4249dd1d265051c3ba3b4c50420dfd2669821475778cf4901e63d375747b46e8ed11fdda47b30d6e3637aaeefbd7f7e3e1801ef29f7895f497f84e6ccf086bba72dd3ba0f3d03769c26df0d4606def08ed69368db7c1f8c523b6f6235db793b7dfd0a6466d8fd87e35f694bff771d4a60b307dd4edb51cdbf65d833695f41a0d6f6ceacedf2ec0fc6cb667ecdbcc7782c8e8b7679036d16b948b5455d335f4ffc08d57d3b5fbe28738f766fcb74dd3346ddb36ff8ce30a9a00a46abfda6a7b448bb8aea910ef3d9af32aef978637a14d01bccf8688c9db10e9de7bd14793d1e84726a35167f29d49e7d15535dd2a62cf38d1735b731bb3f670f417f2529bda75ffa117fdc6bde8a3e92db47d84f69b517f7f23e2739fd4ba95d28ee4b9c9edb7a6aba6c5f78f9f875c9ec02676d72cd6348eec3bb7a91db7c1a6357d458763816244be10be8811f18999c104f504eed5dd51821d986a3dbc19778f51ee2c61b5841554144b0eaf5bc39bea1f1ebcf3532abe48147198bc8b4294a372fbc2ac7af7fe8d885b0d218eb3a86da73aff6ea3e1772ddbb6bda853a8d26f618d57ed4bbfde8ccc4aafd954950f6fb41d5e553e21a4b7d1288a6a19d560f63c7d3fd8fdc23f6a31f1fc641cd15086b37adf0c719bdc362d7e30da28cb92d0eedd2dbbc69bd0f1ef403164abbba38432b893eaee288167547747093f3eba538eef3c2abfa55352fb53a7361fd59fc508f9db8fde691892b4444d3494db90ea6ffa2400e93a51cb8c76dabe337dffc777ef087fd3176eff7526a2f666b43f754a7e89fb1265d1defbad73c46244f6a3cf7ef4b168cf6284f7dc7bcfe93801ab72760160d242d37df3931f66bf7da7cd5d0cdd8e197e6d4705be434dfd0b99bfd3e81372ac84373b2043d5baf678f745e6225e30ccfa0b7f8fc8be8fa53fd6f8ed82fbcedf1fcdfe0e1b96c18ca375f1183ffef639bc1bf137187c001b0daec9d2e0ca2db58c493b73abfcec9b6588f840ec947f2c3962ac8e53e56f391847bbb1477070aae4b1638170706a4da986de6b4435b444953c7618a0f6c2d8be46ab1c0fee6bb42392a8f26d7488eee8a1caca0b6393dfee8b7823e41561a3eebe085db430b2cca4f2c7991c9914ddbe8d8e34ee4001a48aa213b667c3d9c0131098c08f121b1ca7654033b47dc8815c49833f3fdce74aa63f8c03716507fafc87e50f10d00f8f8fb9e52c8cde54b0e18452dae031c1e4afe7e7e787470712da0dfb86d3ad4b2872ef85e1ceaabe018fd9dedf57be40d5bf6d63f9cb2bda809ba6699bd6e262af908b8bd57e1e209d0a3598a6539b8adaaf49a1217171ff42fed9cceef29607d9b7d1fcb9cb5b2ed6e420ae56ccd1e8a6bd4dce8daad368468158fcb7bf5105b1f8c7a280ecb54722d33e1b22fef9683c99d6537b3d1d2af731f7716cd5a0a05a557cff50d35955c7a255c51cd760fe12e32f8c300d369d86de8a395104a898a8246d1686490b158d080000007314000028100a060462d16048a80c83e50e14000e8d9c4e76589ac95992831052061920c600000000000082004800568e6e088755c770e14657c13ff4a0073ae804ad08cc879bae7e3fe8463ff460185a1d840d37bafa3ed08b0ee8473bb43a84611b561b761fe8473ff4d1f44c42900df42b7292510d0f16b1400ffdd187323650cc0fcda1f5ccf3e90a9b96f471565f1f01263cc377086ab759b76bf44b503e522982ca3a1fd4f58196a58fe372a051ad0ff632505fede3902dd0b0e28381c59063abcf583fa069284a6024e8119c18560ea837c6ca5646305e2813da80e6fc28aa0304494511ddedb9d8134779b771ee0d5b922dc0029a84e632a2893147a16e598024605b61cea6b6bb0268cac61d609537501dd9cf6a6d37b96e44b331a331586abbdfb7ecf215591aeda2ab173f13ad054dea24e1ef2e1df021bc6534b7210dd219fac9c982ca0573e99e183212fa1f46f753055bba051bd7431a9caa353ac6407c197a74af07e5fa94e62406db379cf3749cd2b05d7f0b3c80c7dd2faf8633e63046fda9066f0da8029b08929971b7c9dcf7c251c229d82e64160b7c4c7057aa4de32400edbb91dec055b26d004e3031c0d6a06f4b50b07580bb373a8158c73e966211cbb18b6dac632df1fb1a305700c9512b80bb609af6e1667bb3138e5d6c633316b11ebbd8c73a9662133722d5e5e4959c464c7d39b9327ef611ad929c2f968217fd50e21ef8a2a2fe3ebd9ef28be9abb1977db53cbee3923e2fe81d46288587f6a82b3beb6052921aec6ad7ec80aa38e6d4ac868d0c87ce638793c2f1fbb02be5bdc552c0ceb02e3bfa82e2811e9ec06fac2f08b57bc255716b19978fff53d298e34185c2fa3273a9b09571bce243427822bb4470d6f9ce481720150164fe6b0a0b1e2a24d7db35e6e1a58d94746b7a7936a1bff65c13f3d9bdc6b3d1af1a7588aa29fd8a9735639bd70fa95f433f4ff6db38eb6c31227e5fa2de71e7c9837d2a63737daf521d4a90f78e5edcb38144ded8ace78f2c3cbd70ba5a66a94b050b569f2016b60790e58f6d0529a527bc796d6518b8bda285dd6997ca5a8f7d663400b56cee8726f8a46e382f9b31ba7ff7ced87ddc9f317591364c32953a4b9a88ad20d4245c28d5bdb8fa8d032cd62821dd85a9bb4421bc9283379d3f87a4cfe1ee7c6d34246b455ce841cb42c0ceff23f97389eee6d048a850fe2c758d1f9a74bb5189484c6ce778063f9710e77b2b1cfa0982f65caca67b7f699f0369670a5a31267284a2c0470bf7e2dd53b27a75430a6f5f08c3b9fff54141df21717ecdf7bcaa507315e4f4b553d7d0ee8872bb1c618e62ea691f3c6515a087c3d062e8b318ccf07adde7ee61ec4d4c7c9d749d21008fa19fb7c423a1d2b984f49abe2f8a6511a8d34a7168f5eee5d120a7c5c9465565cd5957399d5dc2674891603fb28a02c72ee08bd9708d84b6cd4e959ddf76d306679376ed9d3638ddcdae0cb2a46b32ed049e894962d751cd06377edac9d8e08e35b04f6cb0f78a97d33486849d2eff79faebf2e993f9d334b68bb835ff24ae0826cabcca4e6e6d067d04f509bd54d41ca4f6d34cb56c9a261c5b9a555d92a6fab14793bd5adb20b01c7a6d7799370be0ea0504faafdcf3fb77aa4e1cfaa007e297b51c27dd4aab235b4af203d7f626611a496e968be8b6fba5c9c52241bb82092ad27645b10d2db6a34ee4ac4f0c1aa00f5d4321aec991d7e9de28f3655d332bd5bf266c0d11d346415892869f4e6a543391941e67479c0eda0d943c44f51c932720406451a61d8220b9b7776198ea7b2f8d8cd4ad61e5eebbfd0443a60533f5f4b4fcb4402c7a435dcf9be1fe9ae29c31bcfc9107304a41a8d7c9e069c0bacba778bde0d33664fb8ce9124cb533f0d0314c2d77cb862147957a2f5b12a08432aeec60769d0e6d0880d9a597cee60c88928d00f706297f3158cdf61e1038342fd66c76beb8261903f241b11d7e6cb402fc733e8f11f9bec05a9d737d9e3a5760da51bb973bdb86a0dfe93bb45924cf6666b7e3bf401a9411b3aeb8371bb8d3fe7c3a0e1219c2cbaa8151f1203702fde9c5d4ca9e375bf308b87a6d2d30b2c3a09db946952cc68f2edfc5d79fcc1d4762fd82c5343dfc5e97049e9c18df67a39a9ca22ca7c76d713e020eaf0d2d2b57d6a2a21770e2bcb6fccf1f912dd9e594cafe85e7fb29e1b02d8a43c4151c1008aece24d9a58e12994da206827b33ebefee3eb1e8b1bc697d0d166427d0ba606e8b24085ce78dd6116219186d80c6601489d99b58381136a8733d1073402027aaa703266091bbda8a6d7b0fb4009f219beb07c101ee551c6beb4b82abf4d075b9cace24ea600555c106305181b2c6710a007795595b4aa840d582af703052cb280be49554c0462a39a451a30400c63a4932ecf209aad509ceeefb319de86395b88681621fcdf8dcc134b7c9686083b8c682533ad5ea1d9ae02bdef3e7ad38aeb8db70e19c6e98f1a50e6c8bdd95764196c8ea00c617b7ab4688d7c7d6ff6b5b0076e068f1af690a5f50f2372dcad7a5ecc37445532ed58f9a4583117b691665637471f2a041d9c2209db62bde78b46b164d6edbc5a6dac8fb103a6187262cec959e9baf06376501642eedb17fc6068c9eadf85e466cd6e5a0444fccca5b84ad3a5fd43ce384820649074816c187f95c57aac91bbed46e32bbb1b2f6bb472eb1a4d0e289e6871d7ef081f2a42ddb8dd43014b8e79ff676a4f346fdeb173762402684da01cf43dc5752b8c479c1acea6ead8407d08b6bfbf41a5846ea5ff84d3fe940cb4983411392db091a0869cd3ab5b6f6878b01a743c32bd0d5acb7494eadce3e4e5f35168297809ef854a38ae0f254ef156ac9db1c857677c9aaea04308a5e8720eec9f9c6ae26062bbed110656d5b664f543cb1a9fa90331337bb8187bc60447b9252cc2a3aaed167cdca057f21a62a107c88ffbf7183e0824cd889c827bbe58761365ea431a42462333add2f21fd9cd662941f8792a6e8f934e954e7b0bdcbe88d048531806bf99da927008b29e95e9dda5cea4018802300dd0d99e84e773d8e4def750a4aef96dd8dd91d6cc6d9575389d14b2ea7c5a3dc26b0cf5e5b37985fb2af3c058e2388f97bfda4437d410dc379978e60260e5197a721acb0a1d2c038663e015073f3c2a882b4d1b0d5a4c0522fd0d63702a6c9922c58edfbd9fa901e9c81124efa626b477d3d2aa7cbe11327921992bb72d7fe1a3726e3e960db8628e9dd4f80dcab24fae2b132c0f39be80f8d646809b49d72609595ece0765807cd93332f15ebfc0890a2de617c84c0e2565fe035c380ab33c3eac2d42795906a7001d89b14a364945b973de22ed8c70ae03087b000d9372260d1b6f2bcff900061ad872abbb9f4e45d93a24ba1f2c780f9e361842571a70fb04018031f8714a7d2c4ab4eb1de2d41cbc24f0d13f19e5b9d85f8eab2d3d72f0486144f0b2cab6e37d60c91c83a143a168e49fcd1a40efb6d454918aad83b27404d50e82c73eaa96170988480364b8d250d9a2d98215f28c0eb0638fda0f2b94291c5c33d84aa371417906341afd33e8c752a17cf31f3fb4c9c2b176d79a559a3791871a81e7b4cda48eb3420fa6fb06787aaecffb9b49cea94faffc30290641a6e77bb28db6c0169a3df703bbb35f00bdcbb59d40272d529b46498d3d9896fd5e0d90fbf6b5bd24930acc28737a87cc0484d5a2b796b46eda2606067b43cde10b0b0bf6a4d8ddce3b475083620870b71fc1358669d2030037bfd2a277ae08ab725d89614392ee80d99b0dfa2bbbd33929a3bcb5e957e1eb4560085f48df6d18424ed4c2b5e00da4f5edc4a967bd2d2c562ed02d2d22b00dd7dc789faacfb59c4246ddc2d144e3046bcf5cd04b3a2b7ecc06ce8de9c6c692f8fd9aa70ca29a070661ffcec86f4ed297863b01f22496fa5bfe9e25bededcd9af2fb7bfb038bceb63f0169697e6cb98a31364fba4b79deb6bb3f04a3e6a921990bb8e4c3526bb8ec57abb45cbb19a81849ed41d750afc516aad76bd750ea7d9942f692f13fe69a52f55fd5d484c3607374074bb4ca0aded33799821897752d34db34b8848a56089c6c364a5e7f0a3c99172f1b0581796c6b3b19e218e5d12681b6c031c7288e59f2d06cbf0a5da1bf9d166f58c22615a26f1b18a091d3f20c9285a679c84338de3ff2549bc572dcb9f35ee374889288cb8712f6d036ddf6c0b14fe55144d1a8251e71c5858308522cc9cfcd0fcf62fda287b7d4b11be8b0b0b66a9f2a905b4b124dc097859ef1d5af78902f85067d251496f65b7b4135d8838a5ab339047cd2fd6ca8d34977b5c4581eba5eccce82e4da0dfa3918d49a6cb91bbf53c7de85496fdb1974e4d8a61462bc814c2b4e076859f7da546cc0ccfcb26b00ee431ea190f31873b1f0512475a27a41637e046d01ad3471c3d5631ccb48efcf0433e91fdefacf9ca8b0f5ce809961437a7ac6dbed2741c92811d08abc703e43f623b66e4e4109cb3fce36178a2dc733947b0a3b4e82d40a8732ff813565ccbb1ff6662892d5bfb35757048e0fbe6a007c51f79b75d99bfb6a2db86ae89627c6e7da72d7cd62d413ff6328d4745176e2dc9caad35c3b70ec183269db23f88ee3c0cf0801ba7d699a0398708b550df4e633fcbc68b738d84f19fe5545dff0f2d25cef833a074532357d86730b3dbbcc3e2ce30320d4a7ed6c9f02815644b1de5258c63cc74f7ccae81200b18f6661d276f33e5e85821baa46a4bceb9287764453a3ec7470dc4217f7689c7ca940d8535a261fabfddab2bd1b7a852e59d70bfd3c64c2b6368ce1aa061de567d548578b6587e451c230c885d8619113717b69f0ca80650af170a3295ac05ed0ea478ab7e1e6c480e264e9934d991bc3b841316ec937940f37b2394943c13ceb87a86803088e4dbbfefd33bab70feb28b1651e819261cf7dd64f9add4fc95986c580f1df1ddc94080d8126d243f0331df21fcfc510a1c67cc1d96ecee7a8098a9565359d6083f2646d04b72a1c9ea054ae3ec8d9aa95609231b837bb87c032d140666243d3fecb78f803aadef2706532b883b76153a78efacefdb446804e686c7f563765b50eb1adafff18c66151c052eaa037b5a73be411bdac4f5734876f79989c0bfc7c99d7af1418b5e0c3e69f8753d50c7cae0ddbe5a468e146272cec972ede849a4651323480385f8cfc9ab90879591d66916ff9622243c22f0800b4ff5fbd2539add41d25a6e8753021685f0ed9eb751b065726691c6f21d563d0e9e1dacf36b1e74777cf076fd7884b22508cdb979466463869162c1c7e7f0e4fed93930558cc23a25ead84b3142517d54a50a3ea58884038d8452d2e6935bb8948f0703896c478f9678e1aa618638b4ee5ea47e827c665001bf33ce4d7580a239a3777439b383c326d8605dcc5056376649bda1851ba5eaccef7d94820b440233ef3844ef4428803b4486c0920feb32847011d50d7a5c39294592ce10679b6c61da0314b7300ad0a37b57198e1115c984f178e35a9228fe00257bcbd40e3a00ee47e11351d67664c026d4f68ce6af37a8e1eae3d8d2f105502849d9022ac20e878e9ccde48697a7060a9927a61eda7a0dd8d354069d5801734db39130c877dacd6275049b7a1d3c089ea06355f106b1ebb131b1adcae9b9d0484e3745c1ff63f852f1192d1215fd1a85ad65b9f8d2b4c894a55ca33cbf898481b8b3179d8564ec2aaf8ce304a680b4a6c0fddb80a13859e820208217085a4668b5e0c5c5cd9759df37103fcbe3604d848d4048f31b416215711511b3d556bb20087d51d6161951e44c2374bbf244ef1af54716603d142f763115d52e8c616729b08e8841eff22437a8b86ee71a57617d5a13382cfc40dfaed5cfa3da3e4ada2d98430d50d1adddd38de220b35da2b515af6fcdcbb998570b292b6dea91f2bf2c2cc921d66f6506d939470577ba1380c372159226f0851f78e9dba0a1b714499ecb7828c222640334d9a5cc6e2964577991b060388729d61a17bf3c13132e2d935c559519f6ffb24e9a4bb81705ad18b59958fc05c29308f3452c5a2ab12f2115cdb3074beb3684956ccd6425aab024cb998f7889848bc11606486676742142a7033db388b72c24a4e6dc7e14d84482438e36fa17d282aa2dacfe9efa88eb45b059fdbe8f148767932aa9d1b68402aeedd56b97720d05df71a93cb02a66af461a491f93210f4f0fab9b8e5a4aba89c2be2c2f5bf765942ef02f8d9246f40b9cbe1f1cced89c476ac621d6b0a1d3fc5592af1d403b3aa040764681387528d7b200eb90c6b3f9b59ceff632dbd31b0bc22fed6d0bd6369736055c9392ad8b897ac4763f354a206cf22ff98a2480ff55286b762db24076b76e2bb081d07b303624e12d328e908ca4ea6273b9cb065496c1ab2b47e1c4642e04be02b5ab1f5187fa0de9a2164bd72736b2fad06a0e84532c400fc1fca8e8b9379efef43823d06f1b547cc6ae2be00bb747ef784fa85a7ba11a1b5641128d7981a4ef87dc18604d6a9ad90dbaf468293638595c87a6ddcd40e5f74e7e703c15ea905a65fcfdcdd70a982fdbbf87b292f2232050f03da9aa7a8e2b39ea0fa878fd8a37ed3d5c74d0e7b528ea1be39e7b16602636300745004176d82b8a9a1b8f5fa84fc2e5e23ee2afda27739f100f399ba8e467aef4df952c5bc2fff51a4bde1d30f666a112cc64e23e2e6c3408c56ef8f404ba12d5ea4f6d99043bf706f47bf351b1f3e8beaeda55c59ff47278765221425e9ca0d292a5d3406886864247c14792451845e6df883328987adfc354cdd787de4e825d0523ee6c700e61860a4ebcbbb737faac355116da7318c31ded1b17e3bc46b583eee41c37bfbdb12741c64c5cdcf5e442266fdbaeab9127447bd8d4e83f73955faad80e0e2249129259c6c39141e5ba89adef08dfe2ae454eb9526457e6bc04291519d4f33eaf92831305da3e8d6350739c7c59ccad1258ff25f75b2e1f51f3aba693d52105a95f2e005993c05de56e05b3d129e8ad8fbbecf9174750ec85084a20f1fc040dadc6f2d88f45e54050cbf8ad2a19873af941311382d5859efdc0a04d1a14b1a54c7db2c4d9a7a5ed3299c2c0a57b513fd42164c988007a94d51fd9f1af4c74339fc7f9c3587a429608559978400525b030af2ad3a0ef9688bbbb7131bfe7b1a42882e9ef0838f23b59666ad2a26d3579cab99ca51aacd0549837e25d318a8e5248880218f517a6526fb8cbc61a4b3acce85c72047f63e94e9a1e7f95a65436ec0e4d744c7580fb2ee0312ef81233ac0aaa08acef3f989daf771e9d66b41065ab28350cac1689bdc12668b1e816804d5cca033c29f8c1132aace9e48b153d93918f4f1a2e5777c1611dfd63638fa5b2070dc8f0296c7831ed8fc6c53da265d21091e65f9bf688adec48e44ccdb6e0d028b29faa032674b841c64601519e2a7a8788d5acb724e53af6e3e1ccc95172fdb174ce45fabb6d580061e15015241d579c19650dccf10768b7a8b48cadffe7546d3248d29c3aebe5de45ac2966025c6cd65cefe9692456ab73b604165ce21d895cdec9e77e78afe6b314aa6a384e6b4e6354b1ca97d7e940f31c5a797694747eef40d8f5191cb718de5762d5d8c3032d414a17e749b06fa73708319fe3b300e728e632f824a1a4053345d2d2011e1d1e6d059babad5dcf80f2bf0072cfb67fe039707c0404ef95509091b6cfedfe81a5a9ab29e22a9c8458b26a5ae088408c0e03bfdc5f255fdab8149e5b960ed14d07733e9f722c5d5323cdec391a08830ba56ef679241b4d70f207952f79e075b4c3cbc38da59ce7b530e83a3e7011279ae3a3a3f02d302911361a3f820bfd6bf33865a5487f36e6c4742884e7903211963f54d22b6e3faf321f742b1eca988ff9dbade870b26e45940516a145fd53bb5a4d017daa0de7e1217e282b686896c57e175aefc0514320ee1ebdea0fe3bce192dbbed86a4f6011b216549fb9757818830f91b902c24bb2ea4615003db4033070e328112d2dd6101e9624900d25f0012f94f5cfb8fd1d841fb17664cefa383712702467b5487a23b4be64e0c92c95f0659e4aff30e3cc5c94ce3c829e4696671460784e54db42414328bae5105d4798a0fd803da1b1feb2d22c475299732b4a96d540af55c12393fab93d14943997970064b99114b6aa3b818a5e1f2eb3f7d092c3bc660b60177c7dfd0b93bc3c08569c235f591bbde00b7a62120a6b88cba4f9a2fb5169976c0ebd2818aa145051473430bca06329bf4deea80d9984a297695940b413f85f6799f2fb9508d315f92805eded9bd50b9bcd37a86532fb06df8cc6563cc98d95e047bfd4fbefcd1ee42caefe87d66cdf015459b99485fb64e1d783c82867229b41ed9101430bca8de7083a2dbb5765f2b1d647d2be4cb5b8062435543c37ba3c334d5354e2cde528925a1468da455f10f30b5e5b9ce7196c3f69c3142b620966446780e55aa183d58f7c29dec675030bef701d1a080e83789ce56034707e89746d4136330cf6fc87ef618d8c2babc7e9bd61a57c68c5c8bed205b98f4304250fd780cf88d2f2f49764648036db75af4aaf1fdf185ce5c40c018eae21e1f2a22380fa3539a136cce52c7f8013df902b7530f3d7206288e749560838f2fe8710a29ba05664fcdce43231ce33b8c458bee7b1c0fcec4056f60ebdd300be01212864a15b9f9d11812261bedb016c4e88ba2a0dcc696277fee834e3128412d7092d4f451d5ccc658acce85868afe5cb779a9b8510a07b1304ee20d6bfd149eb9cc44d289a53041424c33e755e4ac6b5da995d0f0d0337dd759f921471d7afd35cdc8c6a54b6c35179331aebd20c96417b4b3c052c5a9b5abc2b2d4824d45123af553a7447903bcf57819d88a6ec2c412f0552f2ec8af430c3b215d2da0efc750d3f6ca4387e43cdbc6a857ebccfbad377fe1055ac379f35766e855fda08bdb73fd79744d523c1630f372c5ba949340766d187c931cbc237f66bdeb4df862024fb54c8fabd66e21283e5f056328c59173a93c5a2eb919a810aa4c19b23602fe25f29ef04b4937f94884049ac77754e3d775bcfbe6abea8313945dfc4f0bf24c7f2f844a36275cdb9e7134e8c2bededb86e763ae59751e3691949880b12553f5e7efdea38222b370ac5a10c3c43930899f9fc24e29c39311085f0ee32ab8e9066d09db63f168b150155eaafbab4b7773e063d53d87b733d8789743835da93d1a1edb73618e78b234a125757026a87366c3180b3c416711520b6bff889a3c143600623a579c55f82895a4ba1969c4e91d9949cf4a6538cf92b48230f8f15e1aa73430d3327084d957e4025dcc92dd630c4a4d7e6094ea381518f54a945eb6eddac51d5f7fa882e58e2d964f1eaead9a01029ea91a9cb0333134e85336b858e263e0ede836f6dec65a1f6744f1c1756bcf4c5806f7a9828391523ad5679da07b192b526c86ac353e5b69b0727b9f68a49e02260be821ea54ab39fd86c3785b8abf52ebdb8a28011cf380db46c838074f37e0c5c8dd803b214359fb1c5658b68ae5fb4872ab1b1c0e3c433403bd0b0691af5a076488bb78374d345a9e8d96a1992c7a586b6f7b55a8c38a93ac5818f3412c4f75906f1de2088ab640b761ae2380b4c2ca499d7a8c6bc54412fa2e9dfd5dc7b3b9f99e5f5a22c6c89ceb01c64ae6d6c1d1f21a98edc8cc2d608a4bc353f83588f05d41010bad80d807f4c366b46a03c96727c47115294290dcbb97dc0a8b9b682d02a61e2b67bb51a68b1e686c18b83e616dd3dc6234f943ec9725fb7b0d0b8452390fc9daf3f8c69dca6fd6525919e35d086cfe8dd759712de5a22f20aae3177d2101f6c6046ac519c15c52af17a093b810959081d3959d50389083c14899c5ec424804cb5e785bb0056a13772dee8dc5abf513efa617c1cfe68030ec9660669ce80d2860c3442103b23c840a0bd5c2db673018770828d478ffa93c8505c17bfd1e5ac76e0431bf453f45efe950b945a64f795c6cacc3ad562db4f0dce6f406af419d140073e8a5964f4de9a41a1e1e654aa7335feaec3f2c0632484b425c8e0adaed76cad040bb1aa3dd283708e44fa40522410c02e329b1da6529ff90d9f0fea3f9799d1f7c420f3cc2939f3470bc00372ba6f40c4322b0165566f7c6e8d6f0c2a6fd4ac9a41697a01e86b53eab8a655470c2a8ca1b2b58acba02d3b3cdc2f71e861d52ca8076abce1d5b4e0b1bb5c49a97ec06e3eda940e5c808cd1b040c06ea6f3f47ef920861544fac9cfdd53ec32a5414398f885b6504e0fea94927ec703813bda8f9fa558866992d7db51d4721d1585d6fdcc0f4633bded5149044fee5d648e489534a82ff02acff00a3c62ef3b9b2a58f217a9ed4a28821d05e7c087a7f04f3eb48230b419d576ac6d441b87d2a540ae952577ad46295d7fdedacf99c1bf5736e30fb724afb4826faf3eed90cf98ecf5537acf79843cfd1232b08566ce300a968be49e2902545c2a177035e12806f6c9b2c1740277d3b7da8ab06bdd93c5ff5b437441743af767bd36197f8704a65a85c928ba188eb68a141fde761a3f065546050e5dcf4be0f864fc5687922fc398e377a7ede5b67f9b89579eccabcb1c369d462d24b48986a1554679e9ea6a7cb510b1368519f6eda0099d12c7ce7e11dcab42cd5bff0a0500eada9e632c6ae16ee25eb341139614d17663c47121e495cecb4be0c6e041a4ddb2b099ee6f3d95a612194ac8ba1270d7f205b8d4810c6150a8b61c31d2caa356df9b0d65509c678ff87943d03d6163e8a7c112e28f2a7d4ea2ace6395e4fb8a0f06e705c3da868481b1fa4cdbaf6d51c582d17b6792eb4f059ae49de8536a8988f742616661d8c8a980f989c60a25621f5592f38bf07fc5f943ac6f3feb306e685f62395ed4fa0eb998cbc883e7bc28ccb82bed2bdf3341693f77d109d46e9a160557d7a7274b10a55fb1d6ffa5dffbcec27ceb1ab3681069770abbda13790097babc5f061099286d62fb4bc8fbb550143939b6fdde9999ebb1438892937fc82de40210de6fda659e0462153a84d55d659ebfd9a9d1fd1ca160734b8bb9b6e52e19715699ba96b4726ed48766fd9b93e4543a309b0fbd1d1f15ebbf1003698b295c2a27275a75c0c651d690922f94a266c92d5b1ffaf13f7a5a2f02998b2c3ea28373cf8d7b5b7554135ef8668ca11a3b1f3358ca44150f8816fc9ca1742f2d2227f054726ac3f6a1890af8088b7f5107029a1ad3db18a5a992f9378cce091db3ddb176828a3e74b4a63d6536687f22e9d7d79241eed62360b85c4913eac15fa9da13ba8bdf1eb51caa6f05604f7e57594915bd497bf26d504e5280fa5eebe983adde0b82e7f61f8b65175dc8dfc386b1d12b5e4c57eb119ee8d5b8bd481531f4b13599ce30f8d229a66bca80cf87e5408578a685eace648913d349c310a70b96aba171bb632c0c4821e717c88b54a9223fa8edb27f735a92c0f57c13981681806d4ef7c5b9ffee6d86d6c6b48bca074452b8a6b54d71930c3fdb6577eeca451efcf90aa012d5d2c78f0343256b12703696915e471eac8ace31c81140ecf2656643b34e7bbd2047804809cd38cb7f04b94d7524ad5f31196faddd18c81006cb363d579d6e5e0affb80569aa35afb282cabfd9147924531bc9946226a992307eb698d3e08c558d994ab4c1a3b42eca5b56aa1b4e3fbfa05ed9854661cfd514470a5f1decca4e08af4670bca005015d3b26f39d3e6e560926a3f88c2b9787fff4ed257623d9351eafbaeacf391ed29515354c02710b5fc13177921570f9da86e261ec0df420ae578e87ab82967c6c6e2b84ccba7c8256cf0cc481637c11f3be461992a3f8b368fe505af3592ed72d8b103dac293b3dad55790d2be899bbb489676b9fa53c3831d4befaad532079cf84e1328b188a56308402e8fdea2eb00dae232f268690f2340e433abbfb5a9dcb3ce0b80d98150055973ebee170e306e4f0a27040601ac0780aef7384f206047ba1fb439d95095aa9804f2820d88b30927edd27f284df3b0238f684a0ee191a25f190cf94a28c62be36e3dc4982adb1538a42ddf44160b78d3e6b5f18536e43e38dd6b850e817a6df0af577d814ddedaae2712900fc035c4331773527c8a06b6eb093da97a4dcdf71e999fe98bbc156e640e12382da73818a0a9bf0ffe884a60440f9f1b925aea9604a8f618d01018b0f5af4ae38df0e0c20f3c621bf4b451cec6eddf86d59162df389f936a2b1dc108b58ed4f7782c2d91982f346cbbc259d0b30bef3b5fac0f9becf383c0d0811ecfe47d1ff0ca463e61f8ca278e097258479318c117e9d2632a87669241f4dfe028b53d129bde0aa1d171f42b374afb8070ee37763afd75321db8b2ec9839080647429a873115fe99b5f8c200956d02813f0e5a252e10248991c1f7df7a8daa681d60852786a30f609d431689072965309a7e1edbf7c6e7d6cf33097a68f33c0452034745cca42a8a586fbcb95db2907e943aba3e0bba3db3df8b5d88ee84cf128aecee9ea513551f6528533f42c3e8b85efd31882ef1c05be68e1dd7b4c5cf49755fbbaac34700e4eaf3001c873210ebe25c5bbf7c9eb58ec458b84c762ef6ff0e1fa1de06de94c3f756a721318d8a79b57083906348b06739efa1e54145375a2c785017e2e4b1984710d84d26761e40a36ac7703a2747ae1f0023d5f6c85dccae1010c420d94cbb9f8c85dfc4f35c240019bb8b486b59615239e5d533408ddf483200625f2392dfa37cc9567acbeafe78c2f2c0dd5806db22de220ac6c8891de36589a4da6dce2bdf2f8cb12ed7c84f40a48023d69dd8c04b9605f6265edf9559541054fe10ad3e5ec7b5ff242f1dfd8b23aa649413a11a78c19bf02814cf2ca52772dbf91c43bd017630fc50808dfc16452e54fb390bf22bb3cfd78a19ab23daf74304eb4b162cb6952b0b003b0202a64c95873204d134afc50acc3644805551c2ee06fd6f5b36c7b3ead4a927f1435ce06b81870e3b54a485871e38b9d3a331b5f56094e52e98f9cf728679f5342bdb30c827f04f5f19b3e431daf2728507340b759f13ffa1ab4533518447c48f0184c2b2ca6a5076caf6364c972184e46109a453da927c7a0ef02e189c22aadf75032b19e5c8cad7aa638229955e9acd9f2d1da07f82cad3a96912fbcb76f800bb6db3cbd795b10de21a2629a03143b268e7036192bd8c2dc3de47d5cf4b0560d191e2b9856f7f9b4dc110dc0d726d63bad29453ccf0a6818f5b0e906a5632b479bac1533626fe9785c0c97f043659c1d0abaa26e532bdbcb09ae52275961444e58701a3b2b06335460000d3cf0d46eabe1c9707c05e7cb0a8c1c31ca6e65f575a3cf09293e9f5fac619ef094680bfe39660c1a8152001b7e33d272456ee02bcd18f687cf4ab1605f2f3603a7bdf1591ba81128d6585538373627cf239bb800a633bead3c1e1fcf5bde9140849a32a8fc2c7a53a858478de2cd083e3ccf386f56d08221485fb8a8361463b9b9682e2214a48d5a692c134d3eebd9d22f2e9567dcb991ebd13bd6a3587e6ece605ffd2c86b1875656e3afe4daead0231cfc733831aa29fd9844448567549c17772c220fc9599c2b379387a6573ca5e9dfc4c5e728b0f08255a24539ed71c556ee0d418f7c04ae98afd043949195ef65b75d2f854c761f6a9e72a51d9d6c2b52c013832c65bf0fdf575b1c4c50eadb004acc40f81bbddb701b235845f66db8811c8569435880e06407c612322c61946015afb1438d40251dac18c2a68293a05cce08bebf167c6c6b5604193e57a8e3644f4452a363cb14f9de4ff430c05bacee9eca85b48b98b234e84ae5b1a6f1d29c8ac98ca5cc280ff5eeb98da06bd06d20d2e8e687f216cb544ea9c7499edbc65df403a61df06fe2c1650fdaffcfd830964930e0b7dc6cdd81f1e873a517abc7bb76471f6ddcb48f16040bf9988eb57511ebe1713255870e7f704e1f53bd6905aad5f2d8484542f539e421b6074f8d7091c5a3b5e59be5908b307ad072f45aa2925f7a17d38f8cd3dad6487de34c9119b45d973c2581b67d01006de37eb5f2fd465c69a331831eb61b697bd58245557f294770a0a2fefbdeada1a344655e528809be88996824cedbaae5862be86518c8d01074c9e0c1a35165c625f8d634dc617fa3819ef45e59d7086f56ff4088d2bf10144a67246d710cb9982217da001e8eb76886dfdc522293a30edeef84f21e5aed98e825c1ec0ffee17e026525fc847bdf4936fb3ea5c21c8b1c1381a7bafe10be9c7c179da728b09fbf0cee431510aa8521cea86cb59f8cc0bf6a27d9b88350d947ac673ab525c3215dea5dc57ba41e423f454acb2b21f45a4356acd677f9c6e05961aa9b90856cc1670c6490930484725e757ee232d88ceb4064526ad08b6e51969adb41abcf4a5a6866eb48e4327406649135ff40e315cf05d7888c457b47d33223834e10a4393419e0f8677dbf9b8a04cb489b09954c3112e77337f02f223ab3d38e6f6d242f51533b4d07b085e9b73880858fead254b0bb971884b75b804590984f311cbdf575554c37f5aa6f70694d6bee2d58944341e6c580f4217dbb896cafb306412309f466fb0a5adc5d07cef6f8f0b49110c44689be7f15fd656ff9c13c88682cc3c90677567c0d96ae43da313d6e88f1230f48417536602fbd5d5840aa4ec9d5e181745aa8fcc0ccafed144f084c116538ca0e584054e451a6129231519295caf9d77ea75a6bf4842ae83d166fae9b2e1b2f6c31da40aba440e14d0ffe3c69f3795eb4716f575c0a3a10f7e4d14fe5333d2d8bff8d5377cbfca91e556b7c87f92638c57484e1f5f190d40844467e730d45c929d484fe91b4063ea84c41f14f3d7921704e6427111db9e94a72673cd9613882b995e26ece8855e9bfff947de8d3eda46bca40bb5ea97d9153dc18d1fbb4a3f04521879bc3052ba1e1fba1bd0082d8dfe40ff2ec5af3fd1af9d6e59bc5aea1996cf4e2aed378e1552d6c08c78e35cf78f628e6aa967c19ce90d7e4e92c2716b84111f94a59a51b72ecb61baa1ee8603bef73a6e29c021c1df1416a30b06de21db8fa4385947d820a13eebbd3313e17e6eb94005a5054d745279234fbd2a821ce06188b3aa0debe6a8f6e9aecd18bea1b139d9999e6773479efbbe0a706a74d0fafaafdcb6255bc75236a14f84f3965304f5f41d2f9ae655287d98520cd81bc15ad3632ec618d1589b0b7d88b604981b6398412e18ac1116702b0299b828ef8fe3dd690555f0970bede5505b11f5ada8cddee1680e6de4bc1aacccdde596c250ef920ab4da033f374eece595fac3a3ac570ac759e3e25e484838306e64852ca4ab35b442094d9abe2ecd30cffc9092ef35f6b519a61ec9a2927b9c8fc810b73ee29bfd6259f7f49afa437c2d011607e6efec9beb064394951f427239922c51882ca24055cca0d5d86e4e9bba1c90da07a228a4c58f6504d1bc4e5f6fc972adcf58484a56ca4aed82dc0656f0a2b1b71af44dc083c070854d179f9cf7682b66ba1444358d66af69617408256b34fea3ebb80c6560b83a1a562f20e56c8ac5600ba2fd5bbd327a218a5fb595fb5f1780c5ed2a8ca6de6682c02d815ffc2a3c1d4e037b5e0bd826f0a738ec73d8118a65b20278a8a402b958717c59413ef50f5186bc7567b7bbde01e4c193323d5a36efc9726583668be2d16d630f253335c7b175269dc6a38a6341e25b2880cf2517baa70f29968beca59364a4d31c6e5776448818d5bcf0ed117f7ac7f9d7b201269d3db3b13b5938b4133460e9d0d559bda55040743bc1d9e96ef702227c7c8ab04c7cef653397819e1dd16096f5e4995ffc271b008bc962c82425778b0d10134765fbbab7d2650ab24dc6f6a2baf34bd1258da20673fef25c8fb6c590476ed9fba6eb1ba0d63f66ec8c6a4be27a8e615b5f43f92df8e085ed419d783436759d22c2e33cb43464295f0e3a2ce222219220a501e1f9f40c7f43306a874cf65cc408d80cac81353c18826659d9f608176c934b39400c42f2c743283937fd2afcb2b0f1f16759397500a0930a366d63021783cb61d8893256dcd817513214d3930171d442c100a8e9a786aac5e0d73ee17eb33bf425113beaf2469a7b58f2a2441cc75a5e6a1c24488d2f7a1758a87ef4ec10a3fb8e3d8091913e662ab9626197ff75f8ae1bd9602e15297ec5876443aa4118b3cf2fd54562b26734aa0626343db7a31a0fd5a70f12f6a133715644e854c26ad8876e76d27617a445c5f73433e9c7dfcb9cf5de5186c4260f5ae6bf4d0e55a2472d0e698c0b210aae59e02cdd188a2c28a878e7f40b731215a13ea0440464fc12f5ece994a85251c6638b487c05f72a6d843d6ec050f86a7a008c74c5b1377a99ba76f154535dc79b301bd28b50777aa9e123c8c98b72754fc9eb02e783b072625ee0b85853c5ea665af611c3109c18fbb51b7099c1941b48997e8d1c2600823696b42d2a62ac293f7c2534771bb4c4af8c5d3ef11b62288722a181c5971c86a5526f00190bb2100a12939edf931ac320a22eff6ed6905d233cc9bab8120f88e07aebdcb8108c6fd64b88f2cc2139f4d626c863a45b47473c62a812b635613e23b0d4e397563ebe982163d041ccadd9a96260d8cc71a8427ae5404fb957ceaf60d49e54a4138d4de98fcaea5e34d59b4e8a309ff3fcfd5082e6b9c38dd3cbe69a3af6fd801fc703306d47285419b6b84742649f88d6106467ec009db859ea3a0e196712268704c965180ed16abe8c282858096c60a321142ec4fa98509b058ecd6d392e5eca014959ef43960cd6fbfef8a003840195e7d8c980a9ff796abf42fe6e0694a64087e4ba07fa750d85a06559864f05b200f55137b07990e8cdf728245460df910d956ae8bc761f9a4a5891e7500858026e737aad2d9df0adece760b47308feec1d063dd7f225e6a1b157aa4a164c75ee46c4d5103d5edf8967eddec803cee1e9050a985d198284203d599d6c08ed769f4152ba2172bea3f90ec5397745615138b7db9165aae246989fa96b6d5cc22c96f4ab21d601954e0be6665b26f968ebf15487af8e097078371bb77bc6a5eb85629a9faac54c827db9c08080e2bbb458c7a15fc897b20fda617852e4c4458128c773f4659f7bd3086429767ca21db170cab0c1ed6fa0b4304c45811c0214f092e81c148a05fd32256204deeead705d01d33b855bb55b2789b259f9120a25d5ba24522da8dd9cc30e205c6d67c75b42cbb4c0009b501cdd3fdc07caf47679c56e85e90efbfc83855aec35432357644a71b1ba3752dad190ec70490e4d0e2c5f3cc2217c75dbb11026610e08413da7a0b445c9f983f9c531f5f92c873a1fad4225e95fd60829438e74318c380d70f60db35a35fe88cfd8b4bf0e66381ba594ab62a558e5b53cf290053a746e55b0f5563d22c355626b90186b98a0a56d242395256be2eec2ea9c0e7221b732f29e006f0eda50491dbb43637906416e0f06a107c8d12e9bae13d18cc27ccb86500b1334160532a44169c6823331c5c565606c4512b4270a7dd79fef2f90c688a4d6eb633a729a0b69d2bf2a523db5c0a8b6777fdd73a96d6510c98b32ad1c292e85645c077f9436f7ddc9bb8861b6f5003ee87abbd5a310b33302edb08ef7218f85641678816e3a590f4aae490194ddf0f8f619ecf8122cc6fa5bfe74569f2ab7b99bc8870518395641f0637b741147756f3a1f4ae1124ed80a4369862d0682509e70906f81015545f131c42a9f6f790d4aab1ad7c314b2a653c7b0b4c3ad9441d300e709c219cae0ea279e765f7e6fe53760886644a42ea6d262b66aebd72bf634cf55ff05f155183cb538558a6f7bb76e7fac1fec63e9f9ba7a555e6544f04790b937145c372d40b1da1d289d43dae39d105f31934260d70a9cc02c4e79dda85b764f09feb4bb084916eaa7118d3b0d0adce12745e6afc920adaad8ac0c36d2d6759f75e9daa6e5b71bb05a033dd39a4c401141d129c18964a2a71f96cc2006f5af952389a2c6fb61d2a12a7af4e7f1d26c6677ea83f9c704e2e14fe5bfdc227cf2024367d671bbbbb53f9b449fe520eb5b7ff474ad36014d229c84313b92fa07d8f4e11b3a08cb0bb3e257d45f92a280cced0b10578f7a5da52247b4f1f73cc8c2ebb4b1b7deb3495509d13a0b0199bcc195e7d6ba2d6e4bed616c80bf6db6e0c10d51f2cbee8274c8a8ea383853107c1339cc61e148b0ae9821ec9af491f7d735641bcd34a51356dbf5b284a74535f80b74c70f5369fe2eb25f61b63d521bf612067616a8f1ed0449f27ed3f67f4706f0f9164d5f99a24ec0515f37fce4d2fe9359d1e70cd3bdeb1a804586bf1962c7cf43d5603b6b05ab8e78e2239ab7b240c7525bc37d4f4a67244faa24c34e0939d2e24c7c93da2489600d752464ab7c3f94347455f99080c1b7704b1deaaaaebd0035659b4bd2d86ace3c5627ac2bd0e41abde10c153bc265c5b214a27a931cf15c51b46155a28d5368b5c839ca43244551d17e9543d969a02e7ac567029561ccbf4afd63ebd1d78f975d274330110b11251f5772db6d39328b430050b6b9e38c4ffb2767b57c62c19c6c75ed55af04262b649fa54f2d90de9587aabaee5a2499da7e51b72ec04a2937989f3955c17664ae4a5b11fec0cd630da31f5098ee9e26fa3b268e01c687b9220114330892518cbca1f882bf21446b74c6c4985174f6e67076720f7b3ac20402e63b53fd1288e65bfdcd627b36c6db89c6d3b836ee478b2055d2174acf0b80c16950eebd2e19468f33284c209226235f45a9231a1ad235e18f53231b1254295ee57f3c1e47bd577b186f2a4cd549f182c888457c6d4e8faaa9f03b3357349465781e2389d348bcf635369004ce8fc29e407c44b4494132a143d46be998d1fdd181ecbd09d49386dd39ac91dd6cf0ab554958233155c58ca9482fc2124b3a191fac72f84ce438bb58c3c6688b2c31099343f1f9b7b0a1680687b5e857354bc26f81ba37be97f0c90e7c9a8499cc70be1e2562c043a81cbc4eed83ca685ded0582d43d442a48eaa9dc1eabfde5da270a59fba734d4830a1a2447c2c2f218f9aa59111a0450c94a442bf6bef4ee4dd913ead52cd294fed29b14bd342d5ba7106d45e68a246728813fcf09d476ac909ff2d25dc94b8cdeb28f3eed24a8e3cefca13d4bce0cad34dab528a14aa3562a3fad5c42b9db2c9faddaac5d83ea9a407ec5dce32df8637b16b47855055c209a2c48c909822501e59a7ba37296e574cc7b72c452005c97fae5fa112fb295e6975103f330b768250bc94b546ff8d6ecbb1fc7946d78637e68a045c87ca6ebf56bc3d294dc8655bcbdcabbb3c15ce3af59770c126c4d2f6a320281758429bfb7640ec4dd9c58ec82f2710ac0a588c2cd97fdd5f142fe0e4589e7ddf1b44e8635d925293cc9bdcb6531e564126a92854635780efce80d9086d653899b1bd79ce0ebd4f55f452451b853a083d9d4d2ccce6135980c535cf4f4d769495eb1087ba4029ca86bf5744defbd03340b4fa9cc3b49f04bb70a3323a1d424838f3a45e7049b1a6c92acad11f9ad6161c9f9d4e2dfa8d60a004f5a582fddcca96e11cc1717241f4d3dd385a9738f409a117a517e80cb3b5da42bfb562b5440bbf815e41a8f2257c91bacf2ed7a390cfa1ccd2bad9be370e24a2507d091dc95be4534521f865c2b3cb9f95457dbf87a016d7f94af3b2679d75e725de599c75a99dd5c316713a12db7d96e17677a3a07a3089a800905c2572df574aa745514422548477de7bedc1d70f3361f56e9d1e498d96e615f9436c8ba503bd1e4592c4f76025855e62069c24cdb8ea3d9d78203540e6d08d2315c02a084b4ae918106532f19582cd9236d5d453dcc27fb3e99ddfc36a0526857cf1e3e4544b6cc9e4d9b958d996ff0a55e93089d10d10024be6ce1cccbb435ef519f22d776047ee0c177f7f4748c010cb81f49212be00e14cc02d23a8dc5bec195543c175c9cb35c4e60a913d0b82304aa7a3df4e9ea1bf190e6bb9f47a93af2146200399307f38e4bcd877d9c748799d63a5a9b2647c81e660b84d9196d0e8bdb33b52b2dc5ca6ac400c1a656b895efba11206ac0995b02be0e26547fb6b10d8c7e999d8add44f604a282a617d8400e902326f68337a929a31655ab4193b773b50d00f25848158ca9a1b51c89c365c79cd345a4e7aa45000428902504c7ec9126d0e8099b982cc4525ac1848073517712344f0580119da23c4ebea02d063b87ebd58c5ef66c98ff6a84acb2386b180e6ce52e4564bd879c61969a6b22179a5af467f9e760e004ba6cc99e98fb73cb19f7a3f384c6b681e2f5d7e28fe0c748447b79e16f0f8e85b03a71d8e2d6f49d4c41c5c9e8d892e4c717696e6122fef8d152edd0e19b391201d10436490ad1795232f982ab5a21c776d9a22b5416fa065db4b580e5d51efbd1def3917df657f4495eb3a5741d645ed625d3127a80a05c72802cd58f332765773e40e66ab4c6e8bc472604a4eae8e964dd4c14ab814638bec117aaa820d0e6a6cfe96d2ae9bc32477b0d6ed2777a4fa40dabf01fb9030982ed15de2027d7e177b47c2c486fac0fa40c560c6f9eae08de2708f4db36ee76da373802229eafc679bf3abd3cd497aa0d5a978d75ceb3b91dee17fcdf54e3700c9b7371cfeba0f4e6f80c03bae90517cca84770cc5569748f218b420589faae200f264e0a0c2c6f0959d3c6684d02517a7a269ff5a022a43857db413fe162f0b438d7e06279247bcbe456df6931fb186df537049cfbffee3b21f78f11d57fac05f57226bff1025c417ee560a8ebecb73ae4b8dbfd07226d731c3a8da00eb19ca53357a5a79b097d70f5ff46342072a86b5d6d01cb8f4e42c8c269fd0390675160842293180ad58c25bf8d3465cf188c5ccef3cab16736e7e8673430239567371ad5804c2ed4adf533f690cdd71291910c067aa5a7db1b7c4b8549389b9494a2bf5cf3923899c91cb4c484ef9789c2469b32b286383970fc6a674d82a22d86b111af149393169b8fb403d7b8dc8c187fd9046c0418c28828be81923aae5170acd8096e4bbd2d3b06505a2618a4495302ab82ccab71d647c9cd2f61051b64a6ad5ca1db0de5cefbd31472ba2f2c6ee62f0374d954b7fb0f737b5d0133fbb06cd18cf31c521ac371f48a51d131424ff7d94d25c1daeb938156a3d93b01b0ea0684ec8981cd532d390330e1eb59574b672249ae7d5ba5f43e7a534c42f9d9823d1b65c782af9086f14e59093ff073eed652227d513de07afed845d979ba5829b6ddd27b2e5625645d2c3dfdc5f25930bea10f2e5d2dc46e5e68159d49f1c9cfefe1e93f783fee7261f902952278d0c0c773844bbd127883f8580674d28609ab36eee906e3a36a095641d91c2ff1a9a68d260a4ec2632c3747d139564b31552e98f3e4749dbea429bd7c185edb8840844fbb7405a2b2dea712328a9fc08f57e3c8bc57b66ac4b6be3029de82e6ae8e9a7ad2f0b38e7e946dea6d9b77818cd67e492d469a54a88cb960c65853adfc72d3e6eae9e27bc48d86879965706b4a54781abee8703cb63f32e03fe31e161df27a7ede5d22c98e78bdb4292a223df7ff7315da44c353ecdd09359ae70d1e30568817d491f59ab447f46a846878dc4ffbd0edab8108301cd9407896aac1054948290d5b170c2fe885f93bf2f5ad421579ee08c8751fd06451970325d4ba67905e6a533d4decbe681152efcc0770b0b86085a1fac6d18e2c2229aba5b7d91cd60f97b4f3084fff7ea3af596eaa5281ef43447bdf64434169fe4603af25d3cd3f84ab242c211c218c102eac21e86c25075275f9b8c9e4b513fac09fc1f67d8d0519743c7c09c37334c4baf072053c836e66f00d0ae3139d74b12bd9b153a0cf4c84e89de15dbaa1ebfc491506d7dcd32575ec3821fcebcbc1957af8960b284f2f1ce147abb7a381c5b6ff47897f37fb1853dd9ed7ec8f8b070288a6cf081c83266954b7e0739b6727e3939ceb03b799a88d02a68349cab16ed622b7b1473804f3322b48e6c6c472bb25e8b4f0c4120992cbe720eeb47ca1840fcab4f61c0cec61c338fd7817074c5a48780406baaf7d4fbabeb4c30079bf76028b41d681e830b58c0abd7c179f23fe6919326e7835a197fcbfe470db305f951d1d8864cd9d8c5e43f683d05d9da67fcf271feb3723092d7439e6b0bbabb7474449e2b95330e2af17d072a1104133e66e0ec6f232e0c64a464c61998949108dd8188bca0db5ae30e9ca7bbe0f6773183f38307885442372c56c0c93ed65cf77cbd18197ae8a3fddd98b7fcc0188ba30e1cd97ff3b7101a0de780fb1f1bb005f04bc504423d4464adaa164a2f62012cdfd39722959eebdda7d0d33c6431b1bac172d4f625e29ced489ec84b857b0076205ce3cb5ab21e5bb75bb7e940fd8f147ecc9b072481bbefc0bf08f8a54dd560e7cc82f9d6511f2e3497c37d058ca91b815bd5e1837cfecf101604bb24ac13d0587eab5e4b015991e6d70247ee6060322fd3616496e10efd58b80b1386d68e57e25b95c8130dc9a8ac8003aa5fb4daef14f934bf252e07f7622af94472b2d1b10798d13671078c8128ef7d997919262c6050b8545c790e104a83b643357b380a9dc67a13cc80e087d9d6bacf2e246ecf2c4d79c178b59764ff5a25ed8e1be2ed577588d1d3baadabe51db85f55c3664133c8f274739f97a3e1b36bd934b922b3e0312037a9b8e25f4dcb1481183ba79cb8e75491f72fa73b7c04300ad02732a8405ce46b2e4d89cbb5b9958e928a39d63115fe2b32ca458d6bdc69b8d9323e677390355fd3e254bdcaea9dc89d5afc7a5a05f27c9a5ad49c7dd0046dfc4c332e8f46cf2762316c36856c1474ed53866314abc1b379ba16d9e8d5739614fafab4ae4af3f1603eaa10a2d07fc7dc77b86235996e95fd5e443bc89994c63a11e078252cbc7906ba984f19d94b0fb6c4a2617959634bdb714bf1ba74a1896c301b4881014edf623f418d1e66b79240645ddb2feb09dbe052a646b1ad9288c2b239eae0b590ef49a833fc4f15fac454212fa93d0c575e4b7dac00da3cdfb2b366e8f1252ff9c03b05d7ecacc326546d6b26a5409f1e14dbce08fd9ccfb3a1754f37e78864b05ea4acda03151d936a331d0829c41a63e9fd6d8299cffc4d955d08a2d12b0ae117cbf6a38a9c2554998aa2c854289098c665d4786b79561d17abb459442377e41df048cd4a4b27cc6968296979fdb6d55ff9fe377eef00b3b0d1a201513f8c205d80a84fcc852fa8a694ee99080815e690f2d3959f13e15a4a007828e11cb94b43ac9b428cc8ac1210850cd3c70b88361b42ca5f628b7b75e6402398e26fa488c2555d7d7a279a6bb21dd9b1b71ebddf92906e5778908bf6f47fdf7703ebd35590d0bb71ec72036b9384085454ef98bdf514ed940259ee8634651de76f61455a054c67b0705c50562a1ed1eb8419571845264daa1e69459452e0e1a3e5c8a0580d466f0baa7726dbe2d2a1a3e1b3a2fefda4e13a2a6e9453d2e385fb80dd1ef5cb1c197e8c58cc35b0340a6b2fdcd60bb3002b9f90635ce0ee649b12757d210eb4f08da1e45ef203c6d24b75293a2eda89c37f812cf08ad388aa70b0a6d00e26a5672687061abd72f3c9a275a9c50b44eba3a6837bf2cc17b3d696e16521bf1c6f53faa3ab5c33a1cf9cc9cf5170cda80063cc7ebb305cddf4bf497caa7942d6c0374da6f37265244c54eec9742429a3d84fe528aafea7e9bd78297ac6d0cc402025d41af8d7d677c956a08ea624eff4d766e63964020e1a2824103ff397407864d03016355a6f054e1d02db8e37ca07d2c4805e8d60b70882f03526320b8c5dbb4513aa557e258fd00ec9e9fea694c82fce51dc83c834121bd41b485d30c57f8dfab4255111b81d50bbbcfbc9710f9ea4f9b7dcbfaad1010c9cc82a1d85cbf00e4e9a661dbcf6fb93966032fca0147f4c0ad4d2fecf35569de8bca5c90188dfb1b033f6bad82457b4305e688b2e80013e231ac6d7107c4e382883e7322f28257410d94a78663de0671dd4693eeda808754f0cfeaef21a0d26219cefbe8ebd2975210d18323950d31e3cf3500b5504425de19ce7711378047028c13815b62b39035d5517155a7bba4364d6e89877b58b14cc0ce9902be3c36377ec2b14b7159c9bc459074238a655ed08a0cfe6cd6b9d1f8ab7ff838312870d5e1e7a01b4b34e972916ee48cc51980e3ef092b3cc008b3d94dc307e65a237d2bbfd1798e0bb010ca3395b67fb46c356c22ddcc14aa390df3d508ae655daedde87b59b3ba6cee42b939bc00126816912d13d730a1608b2848953f05967246c3a2637cea76b78593b5a1b88109797c87b73c279be82f2e584d439b890a1ed61e7f6a4ce30638c024fcd76cfb0a5a42a6fb8ccf11061bcbfefd04aa313165abcef8c3fcca9f19e154e1d66947e2b07f8f2b78ed75d5e7c2543a89a519bcf6f71167f292742b64dfa95f2b4a968bb45b3c96df13f3bc1bf10ffb26e1a6a885d69f3628969ee444d25a98f2f1507b25caa146cdd8c27f027af50d9d37527ee48cfbfd4f958da91624a3d218e677cb3ee16f238cb399e2c00a9a17461b25e88580ebecef484bfaf8a11f5ac922f1eaef70f34fc105e47a56b9fac8933131c8e3f0f4cef7b175806377045b44f4bda3cb481ced02986a81607a626b45192eb28dcfe5b466dfc2be2ba56be4c7c63eeecd6f9caaa6d312cb64c2486846ef549521d9cac999dca60b3161e9e46fd572555e6ff49d2973507f48448652d7b40d008980dde15e8a07102d591db3fd04330e0de44a966bdfcfdd7331f20841fccce01e9698326cf2a3380e62fa9951df2b800b57e4eec9d3d94a0d1ea18dc319e27f20f172b05c3e6fbf7519756cc5640ab05564ceab2401e0f1a10559088ef1f3f922139a29c314924fdb194c75441914164f1eb00aa6098b31b087ec8e8edf50e25e3b12717b3e79f6a78bc73a88243c4dc6296b80294e8be43acff6846919640e0dad59d3192f10024433fde05a534a2276b0fa8a20e33c57d8596c9da3e125d66e03dd1f4840eda18bde40c0a50a73563e7c2c9732974d3135e74378b7650998f455e4f18121672eb097bef4a257c01b78cdf4ee194d0135e37886420fc15f9242240c33b8e2f5383f8fe9d98907c941b8577a034c4b06552c3eb0949eb8498fd2fddaf9a783df7a79a15ceb800bb3f2dc426e63707045151982938f85ced9862d8e0bb9aea7030f6ef7a429856266c78022a9d3a8164f07a4547eaa87ecaa408ab4da4536cbd5e99ac9e70491391a027f4d5bd835fcb0a5eab9ff01dfafeb75bd189d884dd6fd96f274f500e3759c6d67d85a437762ca46d0f932af39c06742f79479345f83df3f28d55b0fe66d5d16a099937e25b6e3e2fbab69be6ecdd8d51fb8b79d2615a797507b7b14518a271a027c0c3438c28b2e88cf570aa40c1ec4a990f894d7903f9776f18ac582699798a26143cc1139fec9d0e397740bef54f8888c77aaf1c00933b74ed022201f8131e3b64e2543ded9fd0a54dec48281b14d828379968377eb9847d60c1fd09d75ce1599b6a793c2742c83e949378f24ee44e18d9f3391141fea35c8993ef24c7c4c83dce1911f21fe5489c5c27b92746ee798e4506df25b4568185608bdf094eada5321ee19450a6334e7172c838f427a40a6a142397f8828c20fe84d8028e0184d37f420fb0d0efa066646c2a6769e8d5ab3c0e9c71920a3ab0a0df2f9ba85751bdc7c0521dd3a6fc7fc24352e424e5e7c4e1459ffe84afe7dbd51e2931982297b98902855cc72525290194f185e618ab2cfa708c6f1e6e8f320527c9ed45c02ca010f2b561b022d9181112f2d49e12d6f31f153541e556d33019c316b5d3ff3a2d96044cdf7bc31b62f0605ce81424f90caef3e72a9c07a72f1372be0242068600e7cca2c325bcb1a84f70f633e666ee7fe3653da97e4300a573cd19f553d5cc82668179697e426eab2d191ce7d8906323eb090cffd46f44a07fc1f757c30c1a20f5746a9e67a444831d244dc2b0eeae95ccf9d0f4067e00ed165e5d3a3b4825fcc579572141fff07446d0282828e33bb74b3d082a94ef6a50e2b7c4ef0718a70573be464d4775df6b799b326f65531add8da70c7352329d0c9a9b6bf70aea2e6064ec309a7903b18820f6712987c751d9bf927ece9b6b09767172160ff67353449a5513bf3cd68061515941c6f80db6f6f2ea5f64cedd110f9260b6297f21bfe3fb48ef8b5e3c0723f7db0abeb00fe4afbdc3c0891605bd864efcda20a261915296d23a970cafa0e73161d67a5f38239308e6b0f6aec65b47563204f2f15046f29692196c2dc55a6fe6f91a7ee3add7cfaf44dd91a8c18f2a7f697d1c3bc9da9b36a0641bd68ef40dae63837801ed57f6bd840c007269035dfa7b4151671ea0161c9c149623c275ded8688643c672c79a01b146ccb500cae5f29767dd06b02d1b89b1a0189fb40bffef132446df94f74d4ce1e2c4da0b09bf189dfdec0c03550f55832b39d72c141064b00408ce23126f9a482cd5eec20d0569b4078884df4b8a6e6a31ecb9a00a14205fa2a9b6a1aa27899fa6cb9b813a25c707729baabaa2b1218c62a69fe13005708873e1472b80b920f15dc99254c8a5223e2d97af60aa903a21b39ddd07db0fe542bf8374b0d4c3d90be188e58858082534f8d9638c2099be2045bcee455aa6b361e6142f5fd64f941fa5e8560e1ade7329b647817e4ac6743f21e41e480a8e5cfefac6d978208f77341274e37b9bb58f7dadbf77293b7a84f2ba9d31cb4fe91900c598dd272a1cf014029115e9971589ff64c0aa8e6a805971a22b2de57fcad6f4ba68efd0f87f58566676fd0434366a7fdcc2e9a0b7245688a84484c53cf1f84fb1297567cfb9e7640ba35d989f4572f061c5b0381c63705ac81305c446f3c8e3c0d88d64b886161090d7b844ffa448465b5f942785d67f4213db42aa09638444ae1be913562baa2013db17a1f1e80c433d8deb67f73844371e24210ab07604a617414a43eb53f92655d68112510d93c44ba765085a571be3cae0d3f62c216876d148411ff2ca5d6ecf77b83c3c595d9e3d740725f1fad52920b40d49d5c020a285e4d1e1b8473d7ac27e5e20c92551f1634c2ee95d6892b31d4de8f61ae8653ae26aecf25e444aaea25e812a8c20dd39b9f5fe5629e9ef14afce4653d5f2faecfac828b01246bb672144ef0523cf696bf62062d7c7781007dc8dc6d464eaa0b52770ba2f84916237e0b825bc00f19995de0f42066705074b66b1ff08a3999e552cc09d2d290048e4211e9fb137255da0f4b2412c758f5dab9cd50a0eb6dc65fa1cda515a1baabb2e756022183a183ccd7dd541bad36b8ba819c4caeefdc6284a9ab1d3044a76f3d98de219442d76af74e9c7f7adac09d8a799eeed3ce730663dbfded80b196da09cddaa9af8cf19e2363121c12f7c0b9fd5d2d13624f684ea5ff36c973ad52839cc6ad311d28be0d70378f92527c2215ac1020c6134ba8044cd0ee6bdf3c4a43e39ef79904983e4f7829f64aeca8c9b95b294a3549fecf00afb8d013a4e0854a0005f6f010bfd1c942ea4e3cea5213e591ef69e28f483509065bca3488d590613445090a19a0093fc18aaa36367fb8d2cc3b574a8a53ea7dacf9f2648958cfa841077f405264c92478ad595623518fbc8d11c92d8190c4746d47968c7518417463436a218e2c72b3d2a73ed814fcb624c8c088dbb76e0b254bef2c8bec133b27292b4fc03705ddce0ccc8a0a598d6526346346f524786dd40828553d3fd7463c896faf29e57f1a0872d66622f41f8bda955d0ee1623ff62f1357016a56d051556425de4a4e764c8e72e64a7eb1de720921daa4d5ea77798dfcf487608b5f4ef18c8eca610b3fd6861e1ee019925f6cfbef530e2275838c36168bee796f1c40299eb877e4b5f0d6575e9dadcd6481e69220c59f5f9192d7fc369c799fcad4bd79b841b10f5359f63dea3dd38fc6941145c476c4dff9a230ab58e0c7d9c1ee4371cd3409f1a2061b7e3b77967adec5b8c347e8d5441dc29f766011bb9996e43fa8773a71c428dbc89fec266eb7afb80abfb15f3449f9e29873c374e5b7a4a1e2e1c1fd69da8825ef23557e213857d995408f64917981e98c01afefffd52accf58b1ee01e05f0256dc17f8d5b56d2dda98cbaace6d0a903006e901ef8c5650e3c44a588ed1443f92a2c5800d1d65fe656f9668a4fa3a585e1cdb074efed4d0995ff1f47e1192dc32ed3007cf1685d1eaa9fd3083530a0710993a537fbf206e3f3a5ea1699ce7864298e0c652b8db3222f3787f26d334a76f6aaed0576ad1d6376eb4e77d3d1f2ca8e9c4c31e8a08ca006310944f53fe7884434dceabd3ef052db6b783559e68bbdbb979233b8ec3a8143f35f779884b90531a9e94475aadc7aea80427868c52e718d454746e102a691b145d6b62cde4c6e52ff62f5d81385b49f4590870d514dcf70970e8276c31c3f05a62b1dcb5b649e2abc6392f39b4828cb79357912f93a7764d37a88881b1b9a09c04064db438c0cdca40e8239ba09666a194edf93323c571930c4877be803befbc83cfde4db38bb693355c806a6fa18c54db6c62c45c296fd91958750eac00857cb2168fea665c38e6d1ed80fbddb586a72011e171b143bd0baddda7ae1669d1d741f51616ea3c2347efaf8a24d2d08494017bda37421aec0da7544625f43a7bc4c3d294c1a80e0640430088228d786430778ff43246c4d94aed8a00471d4549174ea3ddb7be00d6ceda1853399113541c9ee96805404dc418680f8a7c8b9cd6a66c179f2e0cb895034b64868b7432432e9ba907a053af5b44cf7b3584d6f3b4746979b70b13141235ae865f52b4c574d4f29fa3db6731e7781d3eb48d7acda13091c63397d143f58c8d8aa7b5fe5dcbc95101812dba5aab1cdf0ff173a1e684b75b4dd6933f9855f0e72ba74ac897598c3cf3fcb058466fd0fa83fd57c45625c4fbd1e3d83eda4730f56d8b20f95aff8581c25c1532ab5047d4db0688b95b60521b95f6050b42e8de3e3f97fdabb23342c98eb15a05b2faa0312551e2f98638183c21a72c63d90e333aaf3fcd2291291710f44175a098eada1d09a8fe62c9bce955810250988b7ac5b8947ba2af53bc9b2f2b83fd9b45e5e4a74dd86a07f090e524250ff34a1bd01756f5ea9869f7e38860061555f211e7fff5b661b9d3e8565b1b4a7ee73d44f31bbc504689ef76829d65214ba12f38df195f37658d7728f6e31fad114c78cd6b0fce83b39b51446c49bc59c97f8773ad4681c76195bbd22160b8d894fb615ce58db1dc9a1a86a3286d55360452f180b65fc9f744e4e240afcb565e299808bd4f1514a80ddeecfa88fa6c1b500210377d4eb621b9844deb62c89be2845eca38fe77035182613d14caf18c484693387c0a4ff7a68a468bb3be157a5cc1a1248e8ca3e1eac12aa1df5fe4a70a6a5760a4974171d8ab8cedf14e03a3dd9abc6d9428c5be055de3c29e1f5b5fb599326f1c183ce66d73dc871c9bd71f39fe4d11c7e56c76c9dcb7336fb9160c1a6e80584f5436a2cf8b7c3172174eef58c1375fc154305dc007c3d9e01eacc5b4ac932fbd1c587b35e5de9ef2a3fa0333f93ae82da4d435b086181066ed35a4c5a002b16d3b3363d72e2a5381408b9125aeec9124a1e23ae1d144eb36cc3e592f42005ab34de04bcc9bc88b591fe658ee25fc1a410d6bd3ab9d7b745debdf252ea53db619a602ed8637aa3cdd4a14bee883b80266386e25f32a914f2c290cf7f97de45bdf1f39db2badeaddb2757b64f22bf5a709bdb7057a0b186958528e88c478673351779857720e472580955c96f1028e8e8ddd4e1bbd06f56d61bd2503d09079820ba97a6d12e6fbffff8b916b72e4b20189e1c878857aee4386945cbe9fa7a941d5f10b5c33aeff19649d8adf9acfa99ac3015c5f7be0d93488ce9e9284256b1b826f1f7e9d9a7eb9c1618a109dfc37bc23c7dabab2a341d0d0bcd8d86d4c450c1a50bf195d7bc47b97b6a9fc3312d318c2df42160840bfcaaa712557db9efea4d4ff7b48e47cf015f9a49807e208c6ba072cbbd82062aeafa99d8e533eb49314d6c040ba6fe4c227fa19c8442f07cbd814211025468bace3918df3def021de62c147a7a77d8cd8a25aad9f99cc79b76e89b715df2bdb1ab8c7298a3b0e09a485270916b613c0f94a3024fe8db563d3725311295a28520e2b74104d95d2578d0e6b053f241b8d5881edde20175c7a9fd35f1a27163e379a952fcd4c0c02afaf73d7739c3a7f22f550fca50b555751e63c0c3498409a7f9bac47bbac894187b29e15967d9c33ce616b5920517bb79ef92b9da2eafe6f83f7ee7bc16e442f5918d7c1f35ad14486444ddc21f14728fb324ec80ebb4c10daeb8e8aa852c0b91786e1fa4781b879df1e151de7904c61af3bec8805fdcc44027e45d7f291904dcacab3017787b390205e31dcc5ddc595951705ee2b08bd8c3e2d82bc3cdb0429abc77b6cd22ac52646231956037106799e8b3ecaa77ff95633ad63c53997e03db199bb3513347c90fc80b7a014436f43d1e3f6e975674f08c127cdf09c8137d041ce15e80ce4c472ce1090acdcaef38455ae624020548220d40b4964e68230e7f02149ec805ca3dc60efd5fd1bb2e753e64559b82022b90ae5c492e7aed9e613bbbabd7a974ec51fd2677319a82766dcb6e761baef4d7551e8ce21fa6acb48e9392a17a9c4c2d4b2531ba6703d200fed808cb738ac02008df1fa8b0d1029c6bf21e81ac71ec61787ce390ff8af21a6704ea88af707c3993e0e2dbd12f8ae768604a4ddcc1ea0a25c777c65c8042ad884314fe7c50410f383a2a38ed8639029834785b8cc8dd128535c7f51c7d919dd14116dbec0bf488700c365ab87fbf7ae248fadd060e90e1534c03dc3c0e7cedfc06798f0325c020d97c48523d79376a48d1bf690c8c221053b97f8e38ab711168d6621c079c0777c0729589b211895541d38ca8ee2c824bd0d515d84a1ab180ed9882af58d91c2abfeb2be1cc29cb0b33170b89caa9c88d18b4263e1000f2b38cd6bdb649c27129313825110aa4601e8806e92fdddda95b2c04df25caec2f53564f940dfa705cc46995951a9fde27d48af93b3e6f11e8bc29211e713f20d524f20c93d9ebd2eb1b6fd9c889f65d1843a463120d29066d66a942f5d051a8e0d09cca2d0808f3897805c5d7f529ee5488e5409a7cacc956599e850230dbfe54ad79fd20dc8963527d814aace451e77c68cc97515cfb64fb427f235b907fd94d5188d279e62d5f9210706b34ca98841c72bdb20688e0ec7002ed0136a071d0f75f73b2b64223ce3155206ef38415cfa0cafdcda869e00f88474f4eba03e6d3eec1daefaefba05d2c190c724842ea7924f8bc4ee16928c8ffe5d60632d1ae7d8a5a5a0a3b256640a986a6cb21a3b2c77de52f7fbbf3ece88c1039767e0bfff8e4a3f6d3749d1ee8046d8a06041c6c5f0f80ac9839d65f363ac8d35e76e9621a63766913479fe401b00a302b60ca93b09d8e63514ea7aab06811d6b805470dd0db0557a8b4409bd629ec86c95c2fb1586864daf96a53d0459978a2c74060ae0f3be2453ee9748d0fb55dd500ed51afb388797cac90afe5387c9adde4fe3514d02ffc1066835f87fbc00b76191c1e408b1fecf837f58544793f99c59411998dc4100e865b8c8506cc55f519059057a222f666b594adec0ecabe8083c1103e520b3b85b7cb931ba19df66fceb878cc264e62581405f6563e8b428d9596a541138c8da7f01812e5cc7495b08b3448388b25425910c87339e38eae1deb9aa0bf99d2da3473984e5dbb575568cb463723c3ec309740b758286a0578233bddff1620c9b48a2366cadb4e3f5f30ffecc50b3ac655ab61d4d2bd27074a36de5502ebf82a52662198f383f6beb8d842ea921c2355fe535ba8267df5a072db47395ab4718c6fca00ca79771cf192ec300a6756cd1fd7db731e21cda0bbc2e8f0f912c6383c7cc596e63018cc525baf6284090f4289071a26de1590946188b41fdbe82784c5befab86491faa065da737223408cdc29720832d89d1e38fe4b4417c442a1d7410fa9f139efc00b1891971050734c6e6146b8e3c42b1a6ba5968f7c2ff0505344beebaa80d6ec7eab73b66c48a83b02b4eba57a2d004ac7bedc1a0530ca5b961aed5f912992eb30788c0e288549bb511835aa8d26af85f7f5d231a701820eb49046f75771a4f31509afcb605d9bf451d2a0d7e2deb38ebc66b72c5dc3f87078555cb00c646bf331700e4fbe29fc0ed1eff550bb1b5700a6cc1ff43d18612814f0adb5eb8220d728a146637c6b5e53092580bb0e13ebf5148900f85d55ff87c9647b910d62ad17cbcb2c60bbaa15daf69a5b93f187d3f8d5fd3d587411ef763f0df1bfe3803f1545a6613bd444544a089aae8189bd1e52425370be6452dd7215f127c01fcf2df142fdd71295c0be2a8ade7133cfa3ceb2e8877cd14fae6a22d997c4ee16d3b16895b464c749d2e75bbfdda319994c0dadcb84b2358ff027f9cdb99558fa906d78067165f441162f8fe7b4f65f3ec59846d05f4a0d8a38f5055b67b6c4bb0a4de2e00dcde97e66e7a076e4e43c10962ba63a704641949c389308002aa7d3f3d5115e55d7f9d7d43f862d3456e3c75109bda8c22fb3509a4d5fa4a65fd28c6a95ea6dfc4bed9d4acc37b51c54752dc3004e39b1e3dbfca4e07e08bc128c930f92e24e87173651165fa5809eee1a1519b003d017541d1cf223f03b698188fad0916e31753d211958b114d8442a18544545f41d913bd09207094d50194ed8adc038eefa242f5d4b4280194bf7a8b7ede998f5dcc23244bba7d1c09a376c51dac7676e98ec8f084df22b0eefd526d4bbeeb154e1ecb01b6551bb73cadf42168db1b368ab342a0575c219f9340308d0de223d61afef5f36600b437d055a66df73dc050286592418ce1207e81ff61636ba22f249270e5dcc351e719fe2fdee3eef78aa14c954b6382636874a253a4504577b3ea2c3def51f0a71d61b9a00f89ff030e2c45b9a712a0e2feac99af55d95be64f59beea95e11f145c5bcd74da889dbc5cfaedd52bf8346143f6ee5c25eb75e4c756ebb971cf0be9c1dba44beeef5cd85b6a480c241ddbed3f43f13c4b44410c847d42cd1b3bead91ab9cc07853d5fabc9a4ef63e9730040c0d15716ea92e54f848adf1992aa8ffdc551d0a3e4f985ac638f68973d49856756554a96a745326d3d011996c90b58fa3765641c290031cfa3faadbe43c23e8c155d21fec2e180ac934afa495d5cee1eac4f64b9cd15e2f961f12eeec0d21b3ffb4c3294db701620b8d98a964dffd27952836b48011325b1e342b8fc2e696b1c7480d0babb923354a34f8a500307c54051e89857b27703c773d126fd044b0d3d94bdf8374414f7752a6eba19e01880e0fc8857e1ccf271259894111daa5ebd60fe7bdb84bf55fe72f376d0f6bad5ca59733609b4c0a5facdeabcaa3b3e5f281a20c4c413266d752ad07e8e468ff9474ec929d3de8b454e59b5c79c53d17f43a80b9cf950fd9869779bd8e6470ef2acb66e749386995a91cbfc8ad17b7b2e9e07ff5fcce4333f55d55bd30d4f15cd151c8bf59e6cefd6e5f4e2088accce143aaef2167be284faaed6b13122132ae257db1414b0f6b2b16b2d345f1a79813055c7b8fb6f81ce9609305641044f2e79163480bbe53c0460c872a67624b51e41c4f1424ea685a9762298180333783c66b18e99c5f8467e34871e34cc8cf15cfa78a5f3d16d798194ebe966d29983770b2e830811b96202f531395262bf9f0bbbd313c9be746d65bfc889608c43a85f0ec4ef748b2052c9f92744501cb5e25a731e7f2cf412d3c1425800f60691f194311c19733d368237f880964a005a5446e5fc254d67fabcc6ac40b2c4732220518f517db86cc965f1536ecb1c880455e276a3efa95e8f64b1bc13d2597d7bc616d5e797f65a540d819823d942a029d956ba902c931e96fdca3ad60e51ca66a1a2dd34741b4096c5c0cf3881e668f805d418ac7eb6f0d62a4ff9b854d247567081d16389317b30d99513a2b9d7fa9df70984a7b608244b5168916be52fce36bd2b44c22bea392284e608725265fbf68eaebcc6896721019cdd0e122f4cd05facd00707ca36d294a21a8e1de4a919102b03a90ff9adfa90a995f65f29eaf5bc6f742107aa8833a7883c7de87bc93a173b7d28b7fd70bdf82693c47ad5af49ddc8a7559d67e3ab0ada4ee9c1e955cbd04beee204e022f6997447b526494377bdd31e469a3d4c52bfc1d41191983c38c298f5bae11c900411712b2813f10bc4e45396c5ef613d7af5a246858a17810f1b05c8c1bfbeb8ab0400d9a8515efaebf126d197b242a45d5b36e81771e1f87916d82cdb3725c017d8ec8c50486ed988e47309b7bcd819829b339181a14ac9083014c3135359013de354110895bd8d0fdf6ddbaf9e2160dd3d3af70cb56884a4ebf0556eb7f5dc6f43f137fbbf54b3fe09783b73b5170d9f03dfb8e6767b38f84d90960b6ec9352201d6fa4219bba46460cbe9933a58288582522896ccc2f1cfddb56d32bb0fb958355690245696e083c4b3b049c259f0e0aef4f4794e10b5bea6765293b87a4fa9ecb1637e917ae1188e5e58055b392f45db7469d5f4b16cdf828db6306f59b71f5f4359217475f50c9e0ffb958c728113e12e2b8639de13ba2817afc7ced8c1461107aed273b880eca79a810b3cde67147814050fa3b1bff8574a12cfc34a67a53c78013d550c5bb1d7e025b3ee0955cb946d549b628cc35bb88e58fdf79b4d7ede7f03e0f47ddcbc95adb7c2bdbb4180de3dfec0344fdab464f49e73077506399d14a3ee9c090ef5ca3f33a506a4d10810bd5c9a042fd24d54a43ea7e8279f25ae03b426301d3ba0b407c7099c5799c16437356ee1a388a5d6aa4631f2250183be6265944f88a38d019dc5294807f621ea225124e195fdc1b885d95c1deb2e1096d9de9bfdb4e04f0cf1249cdf4f5f0fab6727ba03e4a663b2d7024cd273f0b40af4c24816d68a380353f02e2316831c843024f143a8b3b6bf30a0261544af8c89f684e1cfd3f0e9f79c85c9c12dc86e5657d872a5d51473305e97b6f7cc58217bae70487044cbcca1629f75131706cecc7ba15b5db90b1bd80d38bcb3a5ef8e72121cb8cd9eddabaaa40cbbf220e67297c8ae50f1ab927c97feb2477dd1321c572691d7f48ef1a62c843a96fdace100a99e409b04183baee929a2636349ebd281c2f4d05700b8d9991f2dc355d1c70072a53709b3d04a62342d5b175beb76c73d9dea836c5b0fc11ede5010f22f8032ea22d6f2ee4a1a860f56deea127bb3f0e3c9c2a1e5c2aed3e98d567dec5695053c9c241a58aa0c443fd836312f599c9ec74d2e22ffed3ad1f20ec8d5f63aa16e9f1b5045a80e127ba07aee815b609ea26e909031bc44e8b93c1a0ec39aa3db0693ec4ec70187273f780d9984378682a53d3d1c908d0a7d092e41058cef04c8a4ace673082671bae406024ecc2f70bc7108c7c2f52fb8c5e9dcaaf6df02c4ab73c164579df28da664c6743a72084ecce8168e7a9579264ac717e1c3348eaa34b990727540c65551ee9cc9e414e78471bfc8a78acebd87eb65220d15fca18d92d410d9c299f4da915e55dc017ff17875bd7eb7bd7be5c1e1d2e12a87d087906185f0701da0272f24146362e0b14fcbeb20c077ecc30dc61821a1dfd700206235a8a2c35d81ac7cbbe27112afe615e6e383cd38ba2f0b631500d594adeef9a41d2fcc9e1702efa6bb305578d79e0e62127f5e34f4b78493d620a9083815400550b7bfdd9e6f2831943b8de0b0bfcf51bc1c45d1ad62e1a80373660cd070cdf2c499a60103c45af9c236d7270cd6df05f8fe15c6963d7867ccc628855015bdc77b175b38fc7b159b823302fc5a6f5df143e70161d89407ee91f147bc88c3a98cc8492caf35446f057e3e457a1155106058b539ea1214a6e85298a2ebd4e72e3204a12c5484c1a2db5945d7d12ad6ef798eea2d25758b6cffc5ace51293a9eebf6d20907e5b9f777ca697cfeb34eff8acec656b1aaaa0acff2cc7159f57b335dbdd5b06de12b311ea0f30a769a0b1841f8481033066d0c5391352c0133b383df000045f2944414647cae5f40d21c48f4f1a37d8410e7048c0cc1408f8208122f8e00b19b0800458684006dce101e74e80ce5798421942e0c10e602002259228c289104d7e7c8c14c1e106196248010a94c0c203492001b3a1067c71a85104223c2993d240230b587032840c31a87c208318b480052418c10712800027604504c1e4c787e78b1bc4c0062a9872240840f8e2063280010b5690012a0a3000014ca10c1ff080052b480108a024fdc8b3a36a292309631461063040c109b4d880020ef023ac08274330e1d919e262a95abeb8c10ca0988002a0fc58c40f3c457686b86ab4783409637c71031ac4000527d0e2031b580002a010f1030f0f435c407cd0b06ca83c9a4612c620020d66100318a0e0041fd8c002148080034039028c08273dc8806770210912971a43a8e1090314a0099399290e50801ad215a8343a34b82e94b8c06de1d4018f03dc06380d6c351c4d37b3812b311d8fce63c081ab61cbf1d1d0cdb0e1f064d86240bd60c34697f25c5a6aa45a68609961a5061515ea3b993ece642a95ba8d524a434ac5a494ea0c3e19abfbda6ccafc88457b4f254c34a55243293dd194ca0e4ae90e34a5e2b15cffaec556ee3f5a7dad6bebdbfa905aaeb9d244afd629a531945224300a0494528fa6501ea094d6a029541494863ebbf66947ce721e88f88a07224e2945514a8b503e50304ae90a4da18628a5a1cbb06bebbb16230204c121f2d63c68ea34859310aeddfa477c9db572923a79e034858ef77775ed3c299a3ad1c6fbd407a514079a3a05a13a8332303475327d5670da9edd275d86fd454b6acf5896ebd6feb35b33a59c0328e51a4029c7802d0994d21c34659a01a54268fcc6733ec51d428404110244888d901f427c08e921a446088d901921428204090224884d901f417c04e911a426084d909920428004010204880d901f407c00e901a406080d901920426c82d800b1b1b1f961e3c3a6874d8d0d8dcd8c8d901f417e00f961f3e3c70f1f3f7afca8f941f363e687101f417c00f161e3e3870f1f3e7af8a8f141e363c687901e417a00e961d3e3470f1f3d7af4a8e941d363a687909a2035406a6c6a7ed4f8a8e951535343533353238426080d101a1b9a1f343e687ad0d4d0d0d0ccd0089909320364c666e6c78c8f991e33353334333333b1199dc1f2bc32bb947dc6221194720b5069ad54564838121e005769a904c0dddd29e5144029f704a55c02582847537b878b884908a59485a64c31a61c94d21968cac4b92b0cdda5d20a43776dd993ee2a216bd36636bb6fd993abd05d325d79e081520e01252f28a54e53252b28756df71973d7d6ef932eed32ecfbc48ef4634753a5084cf1960e1dbeab8f5f24da5b4d4ab90394ea0ba62a2875edb3e708e78c715411e851d154a9064ae92abf95d97d7fe4d9e213c57e404a290028a53d28a54a68cad380cea01673a50181803331a3c5315b5f2ccaf4a80922be90d82844488d8d283e4d4c89453076d2b69dd5f2d676f65906cf721565c82a625226eb53a6b6cd72e7fe6c8c83f61bd9f7b7b6fa62f1f250ca1920e39c773ee32d34fe36cf9c718e7ea3fa49464b56a3cb9331d07d23b56d96efdafa9f643572b29e5bac4e13772d7debb8faf1e8eee3e74a8aaf33bb566b5bbab62ec3389bfeb4ed25ce32afbb8efeb7928efd472cfee878fbf8a4ad45f6cf721ddaaf6b2b2de7c57c62a1fd72b9beb4fb9e1966c6f63db128d698f19eb2985df3df9f19d9173fc3b6fe5dc9172fbeb0f1ef99cd7bd65d75fed62430b26ebc6b5bff4862d8b5305deab779df87e5af55f2336cfc31d7a3cff7147fc9b638413a7a93a7fe0ca389bb9ada8ed7ce3e567b24fa6755ebef19ef8963fbfc995dbbc527faa0fd42b56d33a6edf385b759cba2cba5dfc86e5bda6cc26ab2ffd8370118688aa3745bd2d41eee1adaa0a96d079492f525034d6d0da094dea0a92d89f2905f5f4b296da1b484631bd2191c712923be51aae6c40e94d218686a4bdd279d887fcc47f2c434ed2cd776e5483f5eeb6f84cbcf30b31e69ca29a194e2a029ba04aa33b84b59c639bfdfeae3df7ceecf7eb1dd75df2f9f344bebdbd6bc7d76eddeb5cc58e695525aa29433514a6ba0292a4567507c23d851cd3262d6322226c92a53cb35c72c492957004ae946b92628e5084029e704a59c14ea51ca35d103141e8840044650326c61058b0433380268082b18927de183092ce4ceea450941c078e1e8046e61ca137c4827a8400581615980068c17662000d8995a47871e88a40ce002271db0a8e0092b748ba4a417ed58563081952392e0bcf32436f7fc882b863e37f91150a4384e6908e5254fe2e42a6e8239228ae394608e48c2e42a30521ca773144c122718298eb325618229c1744e3d09d3764f34d5016179e17c655be95890488273134c12e7dbca8a9f3e94e72896170e8a87c4c937eec482b3f2a2c4e9254a0f389da35ea048d9703a8fd2038ee794858565a3382c2c8e5271291b0eca3737bd4059711598240eca8ab3f8f68204cab7130c12570ca17c7324549cf3178a83527961c9f1790fafa2ce3550e3dcc40245c5a5380eca4d2f5058361698a4ce37df9048a273144c52e72847c14091e2382cdeb50891ea9ce50589243a578149ea9cf3a1ceb917291b0eca4f2f52369c93abbc4089d2030ecaa56c382abec2bdb0f8f6b2e25dcb4e0e203c6771213a5f71d30b94939b9cb63051028765732450ce21a1a2827ad9706cd8200553a4811ae71aa879a5961c4078cef9500b500b90574aa2b4792611acd898c18976513c2852a29c3a209cd3ed450a27c58322c583b9e2490f51ae78d2c3aba8dbe816af2e896d63b262a30b1b31282ab967a4e4753e704a74db0f2b7465a5449ea030b1c4c639e7759ed76d2258a125dfb66ddbdcf3d393ee85dae11ce5dfc9fb505ef77da80f758229ea3ccff3ba8eae70476c2d3f28d1b1d016249e9b8e30e276e74357ea4a479c4a30bbfb4189d77782213a7dde4b5109e6c9112f144cd1e79cc94b251f3a22ceb722cfe9cbf4f2e4889747c471be95b258a1dbb675dcc9bbceb7e72623efe5098e970acc93239ee078996076f742f9090543e4f9e6304f8e787d30459e735e2a99ba8e6b41c9a99f5e521dabe436c0486d5e72aa4389c88a0d19a438df1c9503aeebbacea5546a29790b8bc905e52d286f6971d6192d35585866b8ec80d202f3a4abc1d2e2e20243b42369d5854b0d95d77069711757b9b8c0d43095bc6b6161812122bb305868b0d060a1c14283abc17d18f0522e2e2ece3ac3658701522e2e5fca6547120b0d161a36dc25957271961929679d9172d9610017a72e2c1b2e6e630794944bca868d6dd5c5ab84721b2fdc70150c918d2fe5f242bb175e68c7b2c1e2aa8decc2f8fc4bb9b0380b0d161a2c3458687462b8701f12be2c5e35baa453e726ba51df91443d4f89235866b0cea03b0cb051ca32837506d10e28f474da91743a9d4e7e72d38b0d2e522727da29373911d98541b95517af2e0ccfbb156f7901e3b552a3c60a0cd1f668b0c1450a86ecc2707181213ac17461b0bcacc010a9c06cef858231390b0d161a38be2c4e535abaae63f938aee33e53a782826151e2881a28af51b4e2f48572a901c3712c2c2d03a05c5e88925871ae068b13b1984adeb5d45861f116e74ead28a6578dcd3482d4a6c4111b8bb79236f758dc878ee553bd141199fcc4626261f9583edfdcebe4b198503dad282c302e2cae52a9585cb5f94b510da72f16cf8613792f96cd5d3c77d96cb0788d1aeea95c585a52502f9397be947f2a18a21a302e9b7b2afe798d9756944d66f3925c3693154ebed275dd0a91c7b1106daf53e79bc9a34fbad70643b4155921a230441ef7429452e2888deb38a256038a4a4e5f946b25b5a06c4338f75a065051f15a76547c47c5690b0b75d3cba7e226ce08eac4850acc469d608836ea83296a45d98694bcc3916432c34bdaa0bcb66f835131008bafbcb0acb02045e44d3955d1b13a3f9daaf0a6a8e05485cae9a40567633aa5e0b40567b3d245175eacc0b4a0a8b4925a514e14384d3945719ac2d9785eda564aa728540c4085155e1559a8a8ac20e54db1a28a2c5490da5ede140a7851785458514516ad28a729a71278533c0a5471a2c0a98a9315de945315ad289b8ca90505d54a9ad28a827a6dd40be54d69450163058ca457e7754f786dde85b175626c3037522995266a784b192d2f3560889478b5f8698361b1e182d4773aa5bacec616a92294975e445f182d8efa84f089f18dc1d998be277c6570362d27efdc0c33ce38b5c0b0ced8644ca70d89f742c1b80f9d896506b72ac17c5e70ab2e5e3e30be2e381bcf4bde7dbeb5943e30381b16ef5ca50994b79458686c322d30261b2d487d4ebf2eb6486daf937766746770365d52f722da5e442c3436996d07949769eb828cce3befca30e3d57967050e4852e75fe75f189f1038201b4eb77d61b0d0d8644c2818d6199c098665c6ab2bc37b9d58502a3044db7badbae022451269253e1818ef94f4a2397c1dcb04bc80420b282e3006b7a22d40d429111796283cef2bc384c2426a65c5cf682551981691f72a9d4edc8a66ef85d492c2adbe9694951503bc883cdfdc8b05b5c212058bafbc78cef2d282d24a5a59394d393dc1ad38cff35e60561c8668f3dc876e85e5844a418ac8258a1315a72a381b17eaa2525e449b7be94e444abc9e6c697849af156779415d21b5e29b7ba8cfbd56941614a2eec5b2b29d3cc09d2430e58955172fb20bc374f23c2f89970763eabace4b2fac3336198e65060b8d2c368fe34a5ed7719c6f9c732b25becdc3c069032b5407a2d3139e9417d1a913a323a30372f2275ea5ed093b65985e1d19409d181debf4e2ba6f0c8ec57d67bcb8139417d79df1ea60883c988d7a79531aa0e2448a4887275e3a70382b1b0a0b291fa4522c3e486d9d1825ce5301fd8197830a9c08c3061f2880008a80d345a162015ad0f03a494981175248b004195a38caf49da490c0643a9dbc0478de0f1e20c5035498c110a6a000c72b0de0e5791e0e53e986e7799ee779385227cf4ba56ed478512fa478f1224a39172b0590e2f2a25e48a9c2834100ccd0c293e249799d6ab06d2728b66de3b826b2e030d0036edbbc48d2c28b2664b06d1bc7754de4a00342133258f9be21e4600508524071427927cfd404064e3d52df8bc8672ab062a309ca79a6930acbb66d1bed9eb8c0b66d1c1786e779a552141af8beef742263032a2a2a2b2b5b161d686969a951c38c2b52a9544aa5c2e285969ded85175eb8d1b239bd41bd70220cee85e3c509326e5061c5c6142c5e38618197174e4c79715d38016546e564fa4a2693c9f47ddff77ddff77da6d2f77ddff7b9e779dfe77ddff799bceffbbeeff34aa6d2e77ddff77da652e9fbbe92672a7ddec9542a7d25cffbbeeffb4edff77ddff77ddf672a79df57e3fbbeef3399beeffbbeeffbbeeffb4c9e69e5fb3ed30e25cf2b79dff77ddf874a7911e509194a602a9da430a9944a271306bed20e567c9e2785e5002eba1b391010450826ce6bc2f3bc269af84ca52d3580299c701d5a5e443e73aac1811515d4e933953c4f03a69327c5b66d5c8701cff34a262da258f17ddf09e505172a2a2a2b2c5e4419c38b284268696969a951e394f2620053acbc008d0ba03cef3b7da7eff3a46060ca0eb670802f4a30c50550b64063025c142522e0021c84600b170861091cc011c00dd0d8c129854263082a5f0a552a9996c0624a799ee721e189cf8446156a944aa91b9e0e4cb0984aa5349660f1e809a6f318404594344a50e3060eaf94460c56707052d2e0c2e739e17910b8c20f3c0005294e5081e33191c601ce48238d31506940214a1a55c0b185cae9b329a1a867e3e57da82e4c41d5ddc0d131e13395d060e2e4a5baf084effbbeae0b4c20c0e7ddf014b003341e308009bc887ce6540302335fc9e4795d88e2e5799ef7555180522a049e67ba9102cf735fb90e7e824189fac9f33caf74e3fb3ccfab411768e0b9ebd0851ba82ca0e4994c26d367329952a6314a26132d956e9c4ea7140e93a90493bad1052967a4f1224ab9890094bbe1ba8e8814c7e19ce886df7444386e6ea4388e37e47322ce44c4e36c4cdfcb6b7393c7bd28d125e1715e0556bc6de3b6ae739693165244299402529befe095bdd72b022b1bc7b9919273dde6463cdf6a1ce99cfa4685733333abd5167482a15d974a9d4e46381b5fa46ebc88b615cfc58773231466db680cf55e9c9ffcf3a1937f279801984a2d464a398c6c5ec439e55c6c2c2055038e530be7dd8b11fae238981c9e17c1d8f82205f362c473ce555a783c98972d8d179112af133da16a70de39d7c170301df77161654be3b5e25246199e129e11ee64a44bb518f16c7ce1b51829bd4cbee292c348c98ba86f5e5a29f172c9c153725307930308ce3b1f3ab9e7411407ca00b8cd0770dadc83e1bc04a301af0ba30ba36319a1af1c9f7f3036be48993c8e2b71385d17d4e1789e17e4e174a552a91454c231994c26539009e7fbbeeffb823e9c52a9542a954a30361490224a059d703a5f512999be530d0d74309bc94b6ea404a3c48bb6e4e031996028104e10c5e9684b10e5b8178ad325d1792c56e8ba1f9d8fae4757d3d174321dd8c574add5cb34b303d16ae694ea5ebcc381764427148e8e8699176aa67ba1bbd1c1d0c5d0c9d0cda43a97953058d0f2c3478f1a9a19190fee09288114a290c011dec8ee6a64f38f305d49b2c674858d81842d8c3f5aa3adcf92526a8352aa85204ca094eef1bd463eed5a37cbbaf5977668c6ac5b9776ebfdfa67f9344b5b49f13fcbf2cb602f662c7b23feb3ac9ae3ad79764f98888decf9e461e39364dd1af61b5f1d136b401ab0474ccc9355d431b56d7335750663e3586b160967539fb8ac5d7cebeffbe5f8e23df1bd155643c29924ad4cffac9a30b33e0db65f6bd83e316ddba39df1d64856f6d98491a42d82d1b63d8215e55a7efeb1a219483ac289ea376b1be6e3064833d7ce6cfef15180948f2894d2209af2e18312e16408273b68aa870f7a7ca087131f68aa470d94863ebe3f6d3f19ab2186e9f0f41a49d6f3d6d2f3ef4afac7fc561124eb395a233b5eeb77ff6c3c633554a8d182524a8493566b082760cc49d21ef978ab975888526a034dd544a194ba68aa260925c2898f9fedf9e4b3b7c6a789f5b3eb7a34de4a73da500d0f9a338870e2add1fa104ec02fb1b84f4ca3022ac36ee427cfd7a01900057b729ab8688df20bdd9dfc463f41faac34a41d264ac61d7d9514411a2dcc3c719e8dd7167dc639e3b548601be9ef0d11f197ecd73219867dc6622defbb938198f1b28c1028a53a34253385520afec6463ebb36e6b3f9b4edba1ec9943238c2118ba1833f62d18b2c01f21ab359d4b1537bf6fcb46d7f88524a84a64030b4e9bf4ff191def1f69aabe92f70cac6f7e82f109a029be8f305e218ebd362c208470babb99aa183355720afa7bf76ae5b486604c46bfc8d7dc6fa47c8737c9a2834d63f32feaea3a9e4479c932b8ec9643ff708ebccae7d52ac892fb3496aae40e3cd98dfe68c9f5f263b71f67d6b5af1f30d4dd723637d1a4c7c52c260335d9a653ef246580d83e51fefeb9f55d8f865defacf271f9473dffc31cb7ce4372e3f88ac224ea247974bcbd0148f2778f00842f3cf7225dd9146ebb91e99e70e31cadfb6084ded4842aaa5aea6df239c67fe4695f6e79f4fdc2ccf174a694f10b848ed58514a573eb3b28b45afc5b62df39b7e2b6d675cf24053ac3028a5dade73a55928604da194dec420bd5f7cbdded7aeadb37052acd5aa3c4b8b544b3cfb9b5aede08db0da6b5128a53434b5626215d2957b6d5bb19a5574f2eff8bbda6d67f8ef8b487f541da827e8883f6dbcaf29a53634b5724a675c5b207a74746481527a034de9f881d7c80b7b528ece838fb91edd233cc2c6d7fa459c4d9cdf089761cf585b233b7acd3f3edebecdf2f7aef48df2eb0f1a5fd74f32fe78776a63fd4cbe36d2fb9c7a9b2f8a557fc622ecde10117fc9cdc87333f2e8d46a5f04abe537c2a2b6e3f8af61251e6fcd372fdaf15ad81bd92d562cbb3c258ffebd5fb56d6f589fcf5defcc0a2df1d68a88f84bb4a6e94a83fdaea31d6f15f70b3d2d87ac46389be66bfcf162f18566d7168915675bd19226d2ce782d124bd625fb34b5d5d919c75e637dda0b1bd9f7f567209bb7fea0f1ad798ae2cf679cf3b9b495cc19eb67daaeb902996685edfbe59d59adab695658c6bb9224165dae1a23ed725d5b6962cdd5846d3cd622129be28f38e7e626c84944fc2523f933de97ae69ecf3e30bfdcfea169ad99e8badcebf84520a030ce890d2f5c849b28a46682a872d2acdab5f5bfeb6fee4ec5aed2f4a690d4de59084ef980311399c2848927fa4abb766d76e9dadcc6598c7c11a499e3217473bba7e9761d7aff1cbdf3ce3ef27cd12e7fcbe3c3471579c7ddf8af745b344bfae4f7e104c144aa90f4dc104a194825bff6c766adfb4992dfdcddaae7efd69bbf5b45d9eb35c69dbdf8fde47e8e87d362685ce27d5fc19af4542297d81a65ec8a094f6d0d4cb045e8c509008271b93ba355e5b348413503f4d5752fbef2a5ad23cc7f1c77ddfe85d5bda90831b93dabfb4db59a29559f14d1d335e5bb41a6ff51076b1d5fa75f8a659691e8ed716857edfc8ce64d8c7df199b9f1dfbadf969432fde97c97e5e76a06fd6b6eb7ddf6807669ad5e51242f3e3474dd62ed75f4b5e0c2b2da554074d391814cc0e853eabb9efe77ce6ecd7304a690e34e530707c4b9a66f5fb1f735d69be5f7bf5a3f719bf3cf507e9b747ef93cb1206db4f92d5748fbed41e8968c9d809e44114d9d9c1d982520a044de1306556b75b9dc17d2d366bc099181af1359d81cdc06a96ccc06660344b446d7bccd731251e1590c20107a5dad2b6d3444b3bf2d6d0f8fa94e2793748718314ea78bb9e5552e6e3cf6ea58926f63fafdd178b366f3f7110941e41831561831894d68033208dd10ece4fd09050b8d1ad8a4d67f063386f3d03d6c45c4be62f214005a5dc0528e5a6a0291baa483a6d49494b24a924519a9444b924da2551279268010a40a90a45514aa5504a80248a4a4a5a22a90049942625112089894d0a4aa9c735a1b758cd12e7b85ce28f58c4b2cbf363cd3353c9d63589ddf6f21861c97a6d919d1a699aaf1bad2b29c2f29b48b52c1231198321d5f286c8c5769b3f48b514adbe366fa487bdaeb1fc40faa6a6c749243f10522d5dae8d03341cb1c5cf198bbef1d547ee32eb4f1bf221212c63d848da33168e4fd3f65a99e71f497be2e80cea6d4b4b96bf758d522e0a4ae9c635f1dbe6a3b17edeb4997d26319da07f194cd7aa59cb78d7f1d61eb2e6377fc85a66eca37525736a158852ce02ffb988a86de972e9fb4578bb5c5a9fbb6ea1176f252b8efe20b04f6a864a29054150c77eb2b5ebe7996fece3a076b256f214c92a3a6ddb239f5d7b844959fef19efeb9fa3371916ff424ec62bbc5aa6fcddba53348d3952623f33f7a00f101844686a6a6ce00e921fa187bf4f01164e681c4fcae79ebd8a965f43e7191f8345166db194d579acbb53336cd53c3beac5986230b4a77c634ed186f9aae3477bdce6ff4d9e9104de148a23338dedf480f13dfd432e21bc9fc107bccd8d0bc6c9409e921fb6a33f3c3c7d7fa0388685333f363668c8da38fd80f1f405e46dcfacc329472100001a5344655487a504ac77fe243c6fbe7b5a5dff8789f56f38e9d9a520ac693b0fb242c0959457bf1ade2c53ee39719cbc8da33da1f4ab90a8c168ff667766dfe31ffec17ca6ff4f323ee99d5a18f95a7cfac0e51ca4131fe16df44fadfb5d83dc2b7e82a99d5a1d9b5d7d6f2f35877d5995d4bda9a8728e5281044b695fc49d62594721390c0c5765b8dcd2fedd0efaa33ab9b52da51a7f444298da1a44833ab591df279ed24f9f9c109da31b233e4c3c38363c487276848c8877686727e922451e213b4c3538467c8674787c78772767ec0f9d1d9197a05edf428f1d909526448c94e8ecf8e12207684867684449bbf3c7d807ebc78beb44339434abeb443e31b6149234fc6acb64b66d7e62d04d48303030528a543b8cf0fcfd02b87270910d00b0693d2213c87a7084fce0e9050cc50939d219f9f1c189424197f8b6786812605c36ae5440ce13b43af253c414094721198c241a03362400e2a94c007f5967c1548629c423f1f18c1c20a8c82d04d0058050258e4807e5888822700600e5a7a40018060217301dd3c03d7426003942b8760f1436d454b0fe85ed063871fb424040774a0d0e394b2be1d05e071436991173450128522d0ed054a3c01021314facdd081184871c60ff5502d6800ac0546f48bd2c5134eb690063501b15279e8220d4abfcaed1434a19c138e804c742084d22e702089081f9a40b912d41cf1ceb0817e03704006929254807e522882022a600929e50106ce48000e28a829878e1f6a449105e57c28a180419906356903c8c087da11edbed0d9a24b0aa21d1090d18e2118414d1368c00e20984210b4e4363738c208d2a09f901888511041012d2d618a70db8245b72a564360b82aa05d0f0d5e0802e90294969114d2affca8c7c3463f5a526d1f75d94a316c35b6538d0784760df06ef8b8d3a9e475db4665e040cad10d08af878d7e434a94a3dbb675dc916dfb366edb3a9311dcc66d1f1743d0b699b68f725b0bd87126d34ac5378fe3bc27366fdb3895ed0adc86a2a5cde3badf36226edbb893122e07b771268fdb9cc06d9b89db80d864d8b68e3bbda0d47d35b618b66ddb38211c0ca76e8b623371dbc675b08df354503e3896ede6b49574e878d83e8ef3683a158edb582e365b003c9a950870d4a31c0636af5b79256eeb68c901db1136cad1542a4537ba791bb745613b713bb68d2b715cb76d3d3699edb4b1701cc79972361d1ce771db4c07aecc70da616bb141030781adc4cdb0795bb7510e887395cda39c35510fb70374f4e5051bf521065cb79936efdb5ab66e0ac79d5cdd16a4db38ce738e05b5da4adbf6cd783438cc6c9c8ae9c46ddbb67ddbe6da382e089d6943715e67b4c170e7b675311b6a85db4edfc6f9c0ddc0ddc0d9d0d18e6e2e9b89e3b6162fd579dc0c1cc76da6cd936d281db69512b795b61a40b66ddbb61cdc0fa61514b7c54e2c1fb701b19db6ade3366f3bb2d9c009e16ae056b88f2b6dddc66ddce6da6ce056b8cfdbba52b76d40b66e5b6da88d65dbb621db0d9c4af76d276fe3b6cdb56da618b81b9bc76d256f13c2ad6c1d77c3d6751ce771de2684e3361a38950db59d3c6edb36d76603a7f2759b77f2b66d03e21b8e1d27221d8fd2d66da8cdc3b1a150ae952172dcb0e5e06d1c67e2bedf5230ccac1cd9366ee3b66d8ba11f35299334b632985cea4b8c4006184ba4388207945423cc0819410c1af402040a8414387820ea1714488a144001f4827f7e8c40544692971baa60c40835cc089102878c905aa303408cd0a203901795cdc6085b176cc2342a60e3685030e4c20d3161155c4b8c0ce096cfece011454b0a3884ce8283cb608346f10211342c2980ba27004a3b4a29f780fb240c6f9879c282c8b6124ae90da5348852269422a194ae682aa5aabb8e3013141500d42009f59d4e2615155369a5b301f575a50e0696a1257c604e2b93ca2988c7e2b2792c5f102cbb6be952a53004208124530dee4379ad161b827820496509cbe8b56a2cc1f9c85152e26d26222e48e221898e4a009ca7e225616521490c285bc9a5c2c18725388f862e8607493c8c9084031014185c7006d01959a289a419504c586e4820a9080ce649ab602189c84619091790fa505d4ba9c873c2004b9c3c5517d36389254c81dad1032827332050835b29f9a0fa8478487e882c9878a1b45229a2b283c989b7e313c28409a430c2040e122003a5454c42002e92564ed90404d052e3b2912069069b25543e212695538d0e088f91ce069522df123c2d42a72339768aa8a08eb0088d444c902483d7b25131b95e6831a9acecc01491812495d3911b6205482a75a9d26602c2a4521a62daf1ea61e544e9381d31a97c33b4e8a074f07c5032dca861071a62d8715af904edb084ca09fc7ab4f400c203f4b1781f0d2557678362f174b80f1fea53f1644a48bc203e6ca51cdd4b298619d449ec84ec0cc1715289010564891c9f151fa795a783a7838903493b6a783a251ea51b503a7835b8d07436309104ca6c9dac8bf1ba5200608a6000be5878008c2db2c082035410400924907491ecc5b00827423459a2440828c90f475c417aac7600400eeec500066948e1094be8e106003034ccf04561032f34900120767a70d90003cb8a898b149ce08a2a3440c505a488020a252b1d32e0042490c619568809218528b000861790002bbb19a2f255a1802780a07e10c606aa7009b191e1c68acae9ab21070946e0e4c71f9f1f788aec5400014e3461438c1f2ac0c2031c5082c9122036386e783800a30a4b6e78b0417da60f44390108a67800030a10000b54a00209f8f1b919a28365e302b705ce0caf0c8f024786b704ce0825313620703ee07a80e201cb0e381c705f7029e8b0e08a3ca24d87930da51a5a66e064e060d86ea85e28d9e0545bcaabc1ad945438d4e9c47d5f89f3b66edb4cb4c5a5cbd1ad20c93b409297c4b4c3b7ef0a4ba43290542ab17c3b0061094f0a1a4f06162a3a60224092970415834a0d380490840ac213a2bb61659b584e454e414c2add101c2aa51a249d4a9074c3c91228201d145460294252298da4120b0d3d4862d9302b4842e1a8c17d434a32a50648816165060830e11920c9e5c5e5a58b51c99c70a8d260a2c4e314e423d2b974444e5424753d34322615931549dd8a8906afb542d36d1e8bd7522952e2f10561a2c1a4622262b9c17203850315c31744d705264c3474593051ea220900445ee93000d8e0b9585c4c2a6feb62ba1c0fa8250613f731f9727c3e25186a6ca695aee4b1745dc7755f77ea502a3578dda7e4b3e102a4a2fa4cdfd67d9e0f4fc6db4e3374399640e150ea40520d2b965099bc1c271d26bc223001135f94bfa8f658118592a4450214e487901098dfcaaa6f7be258d5f5831cacedfc26cea6c3ec5a665c24c80fad61fc471021211fff471d6fc4c12fc24662acee3ad2743db272f3bfa8f41e67e2d23bb8837eb1a585fabacc3a6be5afc95ac4c1106b1fcf3cf465bda1835b63f2c47adff0c86521abe5720dad429afe2cc32f93612fb5f5d9b56fb325c5984d9b59528bd67c11a9345d8fb85c432bf75a7b1cdcda921ede0c1109c7fa79bcbfafb57f7a8d74106bb27a6beb9f591d07c30fbd16f3fd42ced23ab459cb956b07f59bb56786b7efd3242bcbaf25ebc6430eeaf0c848f29499f569ae2fab8ff8a6d0f3e0213dfefbece0a112e75cec439235872b956e6865d58e7d2e80e302dc145598620a530c610a30a698c1145b4c3182294440a98957ee2e97711600bc05007799d85b00f0bb72771131c48f5874515a72c114494c31b256750a1d28a541684a8a31ea8f947a49444020858b140438c7cf7eadbbcbce7012d7eb4a037a5d69e6cd90684dbc8374dd75d479df13e7c83e48e72f4f7db15877d5c1b20bc3f98d805d7cc53735d22e5dae2158ccc5565b6008f11c7136bde67a76adce60055e30da6a5e253f9af54817899884fdf9e44798f84632fa629a030496008513a0108352285480f348b688cee0f8b9d2b4cba5cbfca659fede98d4b07b524a2df064044fa478d2000a3c29712ea28f3049be609996692e97cee0799ae598c15c336c7c5851fda3118bb0fd477f61798f581c5f9ff7847d113661322313e672fd784fd9e73722b1d676dc767cfc45d824c90afb7dc66cde178bf65af2ef9bf83526615bc3ee9b1866969976f477b4b11b976b28ff48620834a1141c2d6947120fa96debe3d3c46d8f34114ef2e3f1d44338f1a70d418045e9104e1c2cc278bffe621dfdc2e329547b24a31d4fa10790411f00034a31edc8e5ba11edaedb3c8b304ee2720d1139fa8b847148b28a0ee08203bea09422a129074001f393641563c09a3e5b24598f1a3006a514dc180735408806e434a00703c4a0e0cccc4c6b86c679842459c5d099780cc85af96f9b8f4a9cc3b0ba7e0630c180cc00211820c4001e06c4c0001b0b4001a5548688e780a3e37f7f3c06d463fd3cbec7802c9ad58fc7dc10f11c4098104cdbda171dfd6585477fc3958ffa7715edbe4fdbe74b57181e4fd8f8f784e1f1d4783c3558fb22c7e3a9433c9e425b89889105d0574a0155d497028628d5f6e6c6e51a22420409e3b85c43b52f7a02064fe0277224800b4ac1fd35bf5f69beebf8f756d2fcac9f34c18b4358e8785fec63c6e2ad2450028448000c94d21d9a4200180740c01208b839401728a5383475001450505ba789a766854a3e5cf9b635f2e2f15692b447b48d639eb7beb6ce2af6da17dd2ab3f98d306d7fc6d6a8d23ea66d295383cd6e254dfd16a9f6e8b7328c547bfc4b3b542462120764c5b4f9d943d1639c265c792886aec7d73576e4f99c599935b2798b766b4b5afd59f48fede0bc706635bf51d501c722d1e618d68ec797bf6cac915b57b2f5a5ddacd755ac1f868e6324596527aeadbcf5312107717e236afbc4da8217fbad4f8aae6dd5d6f5b6b9da237cc4416d9efed792a569da227dadec472107593ac7b0e3ede323599989f3be24c666fd3163bfb648ac79fb337130f4099d26c627f41af9e3addadfb6c290b54f739fd88b042df1ade3e271d4d756d2f45aaefa9e3ebbf61cc9d3c4a67f8c7c2bcb58a62b2dbfe932ebe197582864c956b55c3336cb1f72b0568bf0ecf7b5f58642614c931f264332ecb36b6f3813fec576f631ff236ffd38181e1932e2b3930436e4b3d363644708e6f3c33394a3246848c8e7270716b4a3e3a32494e172f631cfc4c1ad2de963fd3fda1f73990cc7fc58f3f6ea5f544b7f261ee4e3e07dd716c9413d1b9f3cc2b728e65a2cc654a789a776fd1a9bf93473d5f98dc6eaf7bec634b11e3d699615e93de3220e9a2cecafc9dfb5fc46bf726d3f57d7deca6ff44798e62d4d62116f9c4d172dcdac79766d10af1edf3c0e96f9b78b96acc54e5276ad9d5d4bc6ca3af38c65311ffaf1f12121253db56df329be90e7e0e08e1dfa2f69f73d7dc6b5ad91bb22fd3dfaa93d921f2d6a317f4a3b1c944bd97bd276fdd15ff631f76153448dd3c4aa5fb41c17a9254a4965807a09f7c33da14928e570918849d149b21e39de5fe2a75c6c5b0f49d216857fe4436634119b3b945b02d6f6cbaaa6e99a451f36a7cbac0ff98bef97b57a44561f36274dc4e66f7d128df59cbd1cd4b36b6fae4cba9e21469208a294861b9342e1c6a4def958c589d518125b8031d7ca5877ff588de9d7816d5dc99b1b224a88fcf9e475469e20a08ac95a35ff65ff45b419abbbea80623e953859fd08931f7b1910f8b792e0be95a40dc148b25e0ccb3f9bd9bc6130b28a36e3ad2d2d2687a66a54d0ad2b497eae4663ad09a52cbff195c7d42a595ddb5a0c358e52af4efad6718f6ae22d8283cc13672338bf1038bf1038bf107a6352e808d384b00fce2fc41b61f58f3867ac4f43aa3d46d82c6d9231d723461808a9f698b00a2b476cf303bd866ea50d69fd49cab3b4d7f6d42af9230c768493603ca4796a957c9da76020d5f28db042e3efe8cb6396f90852edb91593e311ce62cc6fbce43390cc08a8e66a82faac94d227504a4b9ada5b9c423a945297eb8c7157ade2e80cea8badf66a60d1d43629a5beab7f91d7be88526f87d6c02642e946b9cb7765fd59fba255dd5567ac7fa4fc0cf4b35c93603cf423ce397a1f4ab90de80051ca55c169a028d732ffae4ccc321fa194cb8059e6233fe21236bbf9f7973557d8cb60ba7e16afb5e48f309dc18d495d96583482c930ce26acb665b06dcbd8a9f3df230cdbafc91a538a4832a588941f568a483abfcdb9c69ed427424f5c94ba4b84b5dcb5edf8f98bea50ed8b6a79df777cf38f37f9f38ff9835c2e0d33b5266dddaff3636efd333beed3a4e97a64639c619ae6728936fffd59feb1fe116df5df37927fbc2f84f30b21be290434f4b38c34c4a4b62d5977c63d2f5eec335353d3e3a8068d3c483fdeaaf5e7717ced13c7c8b2d1b531b26c542468094dd723458296e4bc53f4b3538a4d6c7ed41cb9b961ad889462931f97eb2a6186a6ee082e4db4bb96789ff58e2d9aba36ca2c945394492825c249eb62f3f4f1b718c3bb956b49438a7c02114e5a4338016f15222b401e29b202054396b7469ed0a8d2fc9eb2734848923527f47acf22131419e0e82fde453c4456a0204956b1120d40084d1125b167582a28114ebcd5dae4a9b51dc9138b766681a8ae472fbb421b012da4e03eb18f5fdabd33f656b5db7a2bbfd1df1a4ddcb5ac9516331b6393ad219c80f735c362968059108a2fec8bea0e8beaf6b1ca7c20034366844cc7fbe0a1fc4ccb6b64acc6ee1be5dfb7defc4678e63d0ed6c898d51aeb13e79fdd3ab2f0f6b17ef65559234db192a6ef8c42a8e3080c406578673c32ded005a54438f196aeb4f18db44b11adf80225c289b77478bcd61ac209de38571f2bed45da5a64e87e511d7a1d3462f16b6f6b637d1db4ef0bbd28a5329aaa50d46228144ae57d087fda100a8552a1941ea1a97a041c7f7f36c958e83f546ba03414239442694caca67619f622b1925eb55969f9811cf46b9d8547c71b7cd0aefc4fad2dfe1cfa406d189e2838de13cb5ebc9f5f96826541290535de319f7328a538680a2685520a4453b020202b9ba26f0bcec05fc14e1494150106bdb6ccbf7fd43a868a7882525abbb5748c878a382ac229a5b36bf789b3cbb0d7ea91e3ebfaac624bd7234d0418faacd5b7f517afd54454912b113f5028940ae8daa2502815968e196f8dd13259a687910cb620a8453ccac8b8b4b9376d45841ec24bbcf5998342a1546e8820619c526c7273c35a6dfde3cd0d49d61c97eb2647d7845c571f2242a4149bdcdc2c2182847186e0c0103f43b8841883523a044d09e1840a4d09a18410ad541066504a41ec3bbec47ac7908b2dde35b2b663e3bbc3b5a591a74ceb17c553fbcb5d3b433f3ee08fb5bcd8debaebd3b6c6d6af0d6148b5c43e608d246bc65e2367ba0c9f76745fa0b7bc45560fa26b6283549315342129a87b729a841e03fec75cdb7ccfb2c4248937d20e132728a53f34c5c4c564c7923028f8d9ea1f758ddcb9f6e434f1daadb38b49c7b792a76877aea6d720255750b20425519424a1643504c65007869a500abeae34319f664f4e93564c8e194f52bc56db226db3effa31afd592b455862d2cf48c65b4d989cdd35b3563990cbbdf99fdfc467848e8079452219a128a22244b057121e808a9a0a4a01d945291a6809001a5f4079a020209208028a54d680ac80c202a8042d06bd5c4fb5a570cf8b15aed71f05f56c3bb26c6cadf36060c6b7a8c3cafd06ff5990cfbcb5d612d572b5ad9df8f851e03ae689ae0ed2c1608ae5afb7eae40ab9a26a17f4cb4666d3b495a260e6ea477855bff187accecdaf1d6a39a471936abf87f5d57bf5f543749d6d63d4fdad6ffb2b0fc6d61ffb2708b6fe4a10ec75abab617d7aae9ff4540bc9dac2226f5fe126b1ffa690205c03fc2dbade3edb55b7dbc35dba76d9f7d767d7a0d6faf5ea45f3f3afcacf8108152ba84a67ca450aa6dc6de7285a1c7801be3a01e7785a1c780ac6a7b729a3c6daf64f585c65244d230f2f7785fa77a30588bb968fabef52fce21c99af3fa8615e4f456907355837dac564b12e3184cdbfce3c5a6febc4ffca5ddbbd6c6fa4140452226716af94f204a110936ded7496290648b96bbb6fe11f6430428a5eeca5806d66e7599f5d6cfead6ae756c9bb1cda657d755dbf1c7fbdaabef9a3face971b6c63fc22459751cc4dbbfc892470ecab0974fdb7eadff91ebbb352e5d576fe97ce2cf759738cb6e26c997839accd5c88ff02df23ff29de4f4f1331635a61db90eff629fd0653c0e9eae6d4f4e13dfe45965afe3208b24ebb62eb34ee35b9f44fa5cf9f8a659f3ceb69a0e665b4d67857693674fe8e3b7f0ca65d8e6478dd77c512563d66b8fc4416dd6bc7dbfd6d567d7eab7b36bf1ec62b096ff7c42da6a54fdc958bd4a3e9fa4ad45c6bb495b848cd5abe4c998ddf98d2ecfc63e3a19d3c45b3f68e37b6b8edeaff5ab766b0fc6431527c95871b08fd01b6135de4ed6f3c9fbc78cb0fab36beb9452174ae9182997140ae2e8c8643fe367bcf53db3c91a6f5de5bfd7b674517d5363f162d776c4f78883ac9507f5f43848c338c8837a7a7cebdf3589e7b20475f93b63d76f542b0d1cda18e78b636462e838d65cfb22d897369bb93e29c2f6ebff8d8d5e635224abc626cea6b6a3a56951db52463f798eb894d13f1b6d8ee5b28cd130234b5698f95f44921596efa9b24af520a5b62d69f7098bb9b6ee7be232e6c9a2fc652e4b180104408af7cca035abcc0c3803d2c4886fb46dac07590f21a5ee2aa287937e72ac4f3adeaeb78db995c94eede36f99a569ba31a194569ab241bab962a6471135fac9daadaebfccfac4d6e833d07e6d5a9ace1f2bbf8c296dfdd8cef5694f9258c4e3a9f1786ad8cc6a1ad848629afe4cdbb0af76936709d31546be78abf8b11afb581d7283528aaf0f800247a096521a044db93640cf32d6a3069c89898d316ff3169162644a114946cbb85ca58814e3ba8152faa2292143a0947e3425a40794d230145d1b79187accfd7190b563c7ca75e964bdf9f7b5aec7f9dfbcb91922f2a4790e11117fc968614ab200c3912754d244498e6dcb125f6fddff1f8c8d90e46b280c18a86a480b4a5dae1bd1345f3c439b901384a010ca4240423404b920746f85ba1586dab523b3832474852c24ab9f1086f4e0ce7d1206aedc91ec380f477293b72652db3663d9d6d87c3938f28437449884a1cb70adf9b7ec157eec77a8f5e719ce667e13ef9f39deb56afde25f6fbd788e38db7ae45e7fb420398eb6ac91b4d98965a7fd239a585f58098e093c0c21c91082a87c409f1a3ea695bbcb67d73a11ee1a422646e63e09d330da3e5f476e6e54bc75e3ad202711fd7767e4c9ff403eb52faa343084854f13ab5865d89dc6ccf27b9c07b85fc3f26f6cf483069c89896109796bc96ac9cdcdc8e32d216f65a01b1f6f1d21627e06cabf6b16ef931be3a09e5c96fb8590dea726fbc7e11123bf790af1644147d2d272b0e021a98ae78718a88a27658b848e88418f7071240aeaae96d7ce98cba5f7fd3bbb562ba114051ed4d35382940f4590b6ca827a7a7406614646e0a35f353d82b08845cce467a3cd38607e8db5effb252e43d7b696e7dd2992e19783b52f729d4712d34a9bcd6b49990cbb66d7ceaeddf181eea4a88e182f1d2d2878cf59ced1fbe800513063afd189f9d6717d28070c0a6ad6675caebc762b12a539beaf1dfda5c221831ebd4c85332556cb7fe42a9c26ba1ee1acc0baeb4b0c7c5f2f1a055f333e08a11ed5bce5d8e766880849d61c22372311f197f44073f3841b306eb0b851c08d4b7583e2410b1a74718d8cb9d85b392a22dc098658600813d5909c212c2e12b8aaca9543c80e8454c10a4397d995eb9606c3fb640cd216420892accec3c356c656db8b7f1c0c6942af91d6732be4091206a909920242032047408400f16c786003c5e6870da7faa105d50f2b543f6a3f747c94e143023e9450f990e90104550f1bf44882528a84aa7af450d55ca1260a4ac42b67086fb93c2626c677f090e19759d2f5b6de2a7f5b570cf846b87c1ad78f0c8f90f370a11926573fe1ca657807b26233f45a4c043d140a5b2dadab9963844e5c1b6f5db9ddf8bac2ad6daea27591aec58b3dd4a13e49d35b341e13ba0c5799ad352b2a9a2dd00481c60134339a1d9ad2cc0866629452d72709e4317fb14f8e8fb70ae13c5c88d50fb8c9f3c96a6441d3664c3b72d60a1653c72f4b1ea4da03ea6defc91a795aadd54a8679b88fd0c1fadaef9b78e87d34f639fa22180fc97ef6f9a3df667c79b0cfece2cce40827c1196fea81213fa03744f6b5d87cdad10d11f197648c7789b3ec3fcb342c04ad70bc5854b59cf20803ef9347097824510af2f851f1d01a93be4fdcda676c47161464e9ff1d3490e519cb543b7ca094d2fd52b1cef8cfb2553d121a9fa62b29c464dcd5fca0fd1a27d9fad419ff088f77878584c30a4267d75f2b332825ab6a05065d454129c65bb592e14155ab20aed22185234cfe6719ece8afcb35043bfaabd2214587130a0efdfc04dd9a03be18bb4a763843b5c30d543bec40823990e5a681e016cfbcb5bb4abb0120440811e110feb41d6a98810a002c000049c15a25f31b61dff8ee2a446eb122ede850840e3ce860c2228726aa1c00a08209028c14158c510daa82a1c1d4f09285170ba85e8450bd80de04df806f4ac11247c7f1ad655c7ee9d77a51a8abc3c2f19e64ddfad471b986c2a08b5daefbe31ee30e8a676c0c61b78ab0d063dc5d41a0235d72fcea9ac763c07fa17d9ad7b6c82ada6db3d6f11830e3306ce9c8e355f9a7c2a10b150e02c001c80d65a86ef08282e1c63887ae2d2b5cf9e7d6f87ef417b4d97456c813ae4ead2d38fee7226155dd60630319368cc086d086961a485043025435c05435fce44023870672fca868d0828a8612509a833bb875b65a4776d69f79afaa3bdefea4ef8ac47a4d56d9aaa52bcd49b2c242af4f621c0382a0b8df5b7a56f3d76eadc572353f9b27aeb58abc9239d662857e3559ad51fe5b77a56d0d7b3256619eedbecf83547b6e12a4da03daaddf7d639f377151c647fbaf1ffd9d0167c01a23c765f57170bcad9810762741abc3d04f9debae63a85fb7b44c867facf94b1c0fc3203c0c4347c2fde68648dd55c75bd95b374464e40b11292d4dc8ac3d3fab3cb8bb07c0dd9fb46689457cc330dcf11c5c6f7b4f0faa6d3bdaf389e579234bbecc7f24b3253bf57574edd69e1fd8fc806a9d8b449ca448c449446d4bd8bfaceeaa03a508d58d277c490d5475c389036dfb860eb4092f90018e3646c60b5560a1ed082fd0743620504a9d50958d336cb48082a3f61979f60b8d56db245b5b1236fe262b0da6edcd11224818e70811945227542a1ce8f84f863479f5b85c3e6c74fc91eb93b6876c6c245e2cba8931e9323c64bf50fe8d977c2d16e3463849925729a3c77be27c23fe1298fe8d8d6e469e5a4ba8a6d2f216919c6dcb128b442e172cbf19d3e70f94fea0aa140e2a172eb890a133f82e5550ea5a579352aa552e41287597bf5c6c1f87527aa22a9795bb543592a0aa5102d05d372f354c77bd9c4c54357c7097aa060e940edd6820976b880812c6d155fc25aa161e2c658cb7e24c62da51f9b45de25d552c48585a2b61ac24514a81a0aa1519d50a55e9804a658361ecd4b0f16b588f5a35343b804296be95344d9d7ddf7ae4639158f1f62d9eb876316d766dcc3df53d71cd653c7e2bf8b9ac5d3c9eaf4d1f1f050454152b5d613c2ed790ead405d58903aa93124a6912aa3aa1549f16aa6fab3e1c27a84c50a84c4554a695ca840a4327c9ffb196d55b61686ff5d69083ba3cc56c8b7e42cf61e5ac7e2a8ecbe572e91f570e6a2be3a9fb4b5f7918ba6bdf5abb35f6423018a8c7cfa112f0810a35766a5509e98b54a52314c44155a515e895e1a3f2a2a0142cad6b1ddbbe9125f72351795bd5f1a0bba2cb94d21da8aa4ba2ea4e2a6e0746a88a3b808a1ba22d97615d62f163fb3518eada1709a9b60fa83627549b8f6a03808ada4045ab50d1a134ba9046156920a55184d2d035c6743c266c85baf64836d2fb84de0a653f2ed75018d3f11870a5470bab7d91cba5b7c6a2bf1cd46fd65834391e03d274dd5a87c7ddb2c87aeb972bd7e1f18f81f9597a55fba2da17f1f070e479b336547b24615108bb38ccfb673431d7d75ecbf5da9835bfe88d405dfb22ade35f337170fcd3d23e63cdb3e4857d6a8f64d4b547827db00fc7238810949ef1a2747659ad211cfc8cb79661cf311f53cbdb9d0b01a51c08dee64d29f7014ab92c28e5b0a094f300a5dc1534b5052ba4b640066705a55c07424a390e6c618b2d20e9f06cc1c55ab979faebbe11f873112d8441c92a7eaeb70e69a10a2d98946ae1c89116562838ca8c1fd366e49005276421075970220b4364c1f398cf32d9bbb6fe58c87105225c210757d0e20ae3155aac3086154260859a1574a094b25acee32e1de33e7e6ee12db3ee0a438f01b535718ccb634056cce7156c631ca4f3192b6ded56bfe4d3aa605485a12ab0aa50830a25a04216540829bd5889c714b16f04ceb2988b6f9d59acfd8d98821553b053b851860aca984229fd5ce4639f65f785ebe7224890021852e0420a5648218a149090421052b0210a4a88c21694a599c88cf5839cc65d383a1ef3437396a1eb6dcb1d30741788f4e3ad0e227dc6af8d7d945c9e8d7df6fd5bcbfc403044010a4fa094b6a1a005144c90f546961ca1e0e362ac1deb2770e109270059e3ea8dacbdb9f1164d57d8f846e88fa59c70052790c00946382108a54fdbde04322cd084254db0c1841a3081092610a114dc1867afc5ee0fa8ab8f9febd63affc6467a666686669671cc48db5e9ee4cbaaa6cd2cad56c9306cbd765d6975e6fe02d2f1790519797dbe05491c8e3c3bff91eb9db16cc70e7fdab63a3cbe5ffbcbc18c5d861d66bf8661e9b7a22df1c5e293b75ebb3af30e1dfcd93d3a0259de22eb9d59bd72d77eed35c742180fb1504a85a0292098c25c331b738c5f9f15e88d6c92df750bddf854d87843646b9ba4e6331a99c9aacea08c1e830963dc60bcb6c85b2e2c8edfc4182c4af53dc217c9c638e8a8067d9efd28d62c83c9648fc5d9dfc739ff45f0101324b446d2d23c83236969e211a8a0943e4945c08c23c8e00a8f201ea1074a29a83ffb9b58d47e6d517d2664756d44d094184a80db9656873592acd8bcd567559ffebbceecd66f74ed896bf9c4352f12ebde158542a9e02fb10e512894cad15f27abce2059855c2ef197e0b860309f1f1ea1a09d25b01d23afa09f212118cc453b33ba28c4fc8daccea7f84743c68fc93afea86b420e175467f0080044a800118e78a1c50a2fb4844184d05dbae61041064a81c837fa24261ec23259fe7ddf3c7f2c45a4baf5eb0cc2ee111e498cc5fbfb33cce6fd5906cbb0fd1ab65f17614cc266d7628c54cb176fc566594d0d43aae53e31ec4bbb61b5180c8bb0234cd3307c61fb356d8ff608f63491b6717e23aa8661f21c7109936523186cbf46aa25cc2c4f180ca996f68db05ac34c58795e18522d616679c2f66b18b9376c76edc646fb754d84695dcd5a0cb65ff760a5072a65f0800c0acb0f6bc9b86b7c197d92663ebd45295d020f1a4029a5940e8107413c28c28316a534635829225d0b2b452497ab149178b0ed400830b2baeb3386ede0891d34a1608ddce20e82505d5f3ab002a594ea7af4d2c10a74008552701ffd1dc7d738e6bc72a07ff6a435b2d974bdaba83f270760502a235ffb3856cf4115360749945270e3eb39f0a18684857240f7c578b748328b8cf7100e8aa054ebb8f6c6e51ab2a1396f86881c21c99a03460e5f34e10b2ebe30bf08bf40dd40043780c00d746c50860d78608307d8e008a5343ebbb6c75d3f3a3f43d7b65adabe3eb73e894e5cf3cf3a4e5c53e2202b2cab2e5b2f8bf4a4ec8dc8fa46e323e12119a66d6d8f7edf9aeb39a3e9cf32af7e8faa29e4c509bc18bd384229f85e83296ad05383f12f1e5d66bd16c324498310d020a4c1cb0c8630030378c5455d64418d90010e9490414c0c8810830ac400090ccc80c10d608004832218ccc0c51328a53b0c8b5847fad063428f09674220077535eb39b3b1b26a1b7a0c88770ec35a5d834fc6ecb5d7cabc765fbe63c76bc70e7719f1e1f1097a3101ef513535173cbc20092f40c10bb07881134ae9786b6d8b15e985f46adf2f351886dad6d0051c7041e9021d5ae0450ba2a094825f8fbcc60ac395cef662678dab1e30680b30b6e0c0160bd8a2670b1516b4800501608190155c610556ac40c90a6e80401e03ba5e1ee38a0165d86564a57dcc2f2ec9fa397419d6f8665d71c2bf78571d9a96a62fb656c45a57cf587f3ef729fb588c5681112ad8910223a4a00729b082520ab28056b46dc131564d30cc1f7a8c4b0381e25542370f9458c8f5cc127df621337ee343c6a7e9d3f4adcf1f82d884345d8f84de0a41960dcdcac70fbd9298e6e56f5befe71af3a5dd4048b547867d759f0459ab079d87d7f4083dcc788bb5c8fd9336e4600d4397e1adef499a5ed3631cc7ea35a4375f571d70ac7d51c85ac9f01b6175e8dad671ac7eab51c6b52f5a39f9b4d6e7eabad25e8ff7c44536f6d9d8e7c958bd4a2ece0f847dae1219f942d8e7071ba794c2603058cd24475cbe59dbb0df75f6e48f6fd6862e96bd4e0d09672092469255ac21e1fcf271bf762cbb3c58762d4d575ac6393f8c52aa034d89a00494522a82275e267d89e008a594de1f11ac68188a0045c1f1cdd7f8414f9216c9d1fb9c425a4c01b5d029ab161e023042f004ed81a64270848262ccc5d775a58d56b4a710089c008230c462c6392159c51df041d084cef2791fe73722e6826086523a62f1a6f6488888bfe4a6f6486a8fe40312f8c0ce0760b21082e784ba487cdae8fbc459106551031661504ac1ff5df3298a47baf645b1539f5e2377ecd8b103d4b52fd22459b190227b6111caf07e212c6e98f569ae75e06c8d62e56bfd8a3d130f1cc1035d501ab2683c20e40a255c21842bbcb8a2035754e08a9e2b362bc8a0a0b69f772dbf91054356ceea2714693c0664bd91d53774b9b085993a5c79c8125afd84eea2f1981076ab18228542321ce684214bc87978ceea27f418f0e8af9015596c5b06a966a814f08be6a99e744c219a111000020000731200303824188c464442b9709e44e30e14800477be5e90509989c32c8829849041c41011108101001011481b003d5ae49161de31ce379e668701cc2e332f29c345b916b387b81a621c08f0eea419e060153114d3edd70e8f2eb665c0beebb791f5b4eacf4368e324e80fa288c51efa52668300ab6330e4035d1f206ce45ffa2640392cb7b0a6a3e7443f0f7d7720c93b158ba298a4f4215c2c6f7bd8e0e6ec838a3dbe4bd074d5acc0dac947cf7ae3c475be48e7f23386fa9d38603478161e6d7f6a6460e9503e419b13eab3e148fbb23459f3bfca5d670cfa3e2386def5ede69d8e99af206435bfaee23df421bd5308b456158b5447e2494b4fd06cc5c34dd760f929836bcd1f827cec56daa5b4d4db9c029596e13d8b29cfb73214200b1932e3399f54539cde57b0afbb3a147ec1e86fef4562662f9eba99ec7dda765b321333ac53871756d3a23ee4b9a46bab499601bbb660bb455a1cfc2d6d8a0c8a419c1aac8072855e5ddf5adb1c0378430372d2a766b06e2eb6a8b61e440983b88375e4e499b160de65e0e764760743296fd62af75f6f28c9dffc350501130992ac50edfc32ece848e928ea2e0aaa5c83149d7d9848f74ab2c54c0cc09e337df0d2c5055fa8fb6736900cc948ae05685b023d53630e498bcfcda1df55bb9cb210fd0a50110f546febdd5dec31ec4bc9b620f5ef4afdf2089dc95c60f9a106601fdd86ba03a58dd6fba79a2cf64e7c9b3f35886060cee43a015e673a511088391edd41f88fa036e28ac664d24dc75e3e6976fc4f6f7ba4f3aa8e1abb4a5b5e22a009dde24d23688139316b1cc6ff490d7514388ce9b840a123730fca8892e0269df1293fe1a3421255bd3d4cb5967ba99f1caa02ca2f240ac5423689335accc77cf2e70a1f21fec8b48a577f86e4f907df3ec2e5956996db8fab87ff2fa582a720e339ba7acbdcdba2dc311473bc42cb99f15ca42a22a3a5ea8e849ef473caf5e3797fc184a916becc45b22e7ea0320c66edb76932bb99e40a58d67aac611dcd2b14c6e966ae7bb29ac5b77ae60192281483e569c9dcfd4f4bd1343176e5a60430d9f97e8cfe707951bc22c011d31ae7e1d262e1328994305bd339a07f94b0cad91221d28112ae02bf72652e66fe932dd1852595d7197a0060aea580c8437f6c081a17675ab6cc07c0caaa6ea029c052ed65b90b7a0f644d50e7ba00683a38ee9b40e8c8351cbeecd608e74cc75fa13ca7faffc714252971666823e3146dc7e02a4e515106a89da706b03b5b8bb1052594a5f3084866c3f4e227f02360ff4c504b037f04c3eddd389b2303a98bb4aba4182cccbb996c9f79fb308cb515f4ed0cda9d959b2ad3131061b08364cf1411156517ece4c6d94705781710edefa48b069ecd8bc0c66f069afccd7eeeb209a485267e882a989ea386422f7fc7a1f15d2eca27da1582cf422a7b880db8e4bba42faf2794f7a865c00571ac411df75320be6712e2908ed32fb409d4b5c0140d70694d385598aa3ba7981523d37351d6ee68f262f6f0e3753724629605f02fca4a441d478fca230ece5fa7d5591241e167034ce3af6266af8ee04d07180bfef78691ab4db7624f03d771196012c9fb7923dedbded529f40b2094244a9105402373b93723a87856734c1efb9178aa773faa2b208feaa9c3f08512a7410213c6141a22a097449180e236093cb2e6dd2061e3d0d32f950a0efab0c740ca1041a5c3c2d06a8e6254ad92960f6fba79eb96a87eb21dcacc8657c7110b3d08c9883e16d022fefeb23beeccf3be362682411a931698a209338a1429b513652a32a4d9f1a9e4997857673161b4452ee80b27102f34c48ea1b283ed58278fb0dee0b2af05c030c24ca02b8e45adbe4b893d5a9ca643190599359ea61809c87b085fdff65382ab6ca1d1452f998ccc4d6bd01731c523f6b1463e8915efdbae2695dd2426e3e7fb546b9c1a1af7ee2c6c5aa56dfbc84c6266fc8bf712e37e8dfc4e18cd0b537093ad3e5a0cfbca1be2ba509b50d6ddf40f061c13b794212e722e42a4d5cb1e42951a20bc38096a673094961d7a1a4196d43158bc9085278375e1c69f4dbf43e49a966efd2c7e16e79e4483dd4b5514fdad2bc9d995d3ac6630c7de4fbc8109acf9443376e02157e6fdbb84b2dc10a501c5e8e1b5ee2efda2cc59d63ef2ed819a8631c714c0a2d1c137e111c1576e178130699449db03bf124e0f94ea8d856e0f17f0cf95f5982ccdf97be9d8e2d537b3904ddcf8546a83bcf3127be86136b2a3b532183c2af6a756ffda5e471d6974bdff2adca836c759bd7eb577d80396a8f29fcece9745b987a4ad772aa3491f38b53a44310b308062125bd26cad66fd44484589eb2ca20518ecbce3e7e48ad3253c09474489c93c98e3246c2691d219d7982eec2dc647faf25f71ce6350a00d4eb379aa4217f71b25240607cd58c2335cdda919303743a069172be99d9462c27d1d6c6c0704724898fd8f79f9f93aa69f07c2fbb139846ebc20d10331e8d0a2ea3d32e550b2ac9fbfd7304105bf23f463245a692bc0caa94881e34e4460d7df5d6ccc8d81383c2d45a3b73ca6688f28b272ada7a917de7013bb2924b65ca59fa5040b3a6fcfd6c8f843d356156399efe98e16eb48784f2c6b00bc9431535216a6b244292282d67bb369eb3bed410b224d7c82b91f5e99cfa90c4d4f369f1fd949aa0081a4c5be6d0eb9cc178cac17a25455c91530309cb3a2d539102f5336c5ddb47b610f2de533b39c0af2ccac65e0d987f47c0244b31c68ab9865507f6b24934acce953a56757e07b3e52b48e9534bfe8846d571f29bd3761c650d6a045d83685e349d8623927f8f734b8667fed534b0cb70d115bfeabd6046c073607f6b4256003b831fc32473a31101dc249593c0142f85686911276681b7a0c09dfab4ac2aefb77ae33bda31b54703167834ecd8e8c0f3d35715993af0327bb0697c0f2ac87a5c0115b7081bc274ee07dd4138aee6af7208ae374651840161177755a323f64544aa9dd7e320d50ae2e14dda1ae0ef47ec44800d4e662d3ae85e2eabd2dbc629b795bb9e78c29649f19969a583c0a3bc29f318faafa9d4ed8f499b03bb29c22f21f2d63409512896dc84b2d7b834a18bfaf5c1ab6e457100cbf7331ed3b2b859f89a555100bc2a5f2a4d2f6df235f910daeb69acb07037ea74846ef0cb18851b75de51bf3ac8f45b71dafd0741106a94c7d2d63937f4291e04b8e73cc682b6c18e02f836bb0706424c36a0db252383cd9dfc30b3b14768a7263323e9c6b7e9a0e28d16b458ce233883a44cc1e2941484bfc59dddda2b228cc6749ac2198302e2071dcb92850048fa991de3961ca5cdb3e4ef4cae96c46dc932538db9fc4b5102260970298989269370948b50bf1e8959677c388fe1af9b4ed3aa189c9963ca163ff588a91e02c16185dc6b46106ba54721e9ae958d194a36d767c746a08cb26b4dd9c43dee07923af43bca88c7ba8c46f0d85bd70f3dc1980effd11847b4fccf0fab9d7b0d07a76a8759a425785d337725dc62254a1382a821e1f0e16ff77c7a01790dbab3145c168e4ac3293ff25eb619610a09e47467b948de1157a63ff12523f82669d1fea15159154843b30671d779e900d8527d655b484fabca6d38b09c2735b2fed84ca6c950aedeba6bb371b2bcc7a40a09b5c42ba0c6cb69778cfef56a03afe0ac0296993a6ea4df265e365519f64c933f8b139ecdc1288cd27dce3b3305ded3080244c6f0528f6db646d55ab179d6c8809c3d9d36ce7dbed6835827d9f6d27cf9faa5fe79a04847900f28de7594268966631cfca3a8ef31bddf610578d63c110590c1739f7c49270db1dd1f915d62fd80ef05de7c4ca81e9967871aecb2279a15a833015844682dd38d80326f0c0f206b8929b09723e857f900e47acee42bb002b7699d240832d881f0e33660b911b060c6d54cc539510c8f78c92a0ad2fd4172c6c2ae66a31b11092af730d5f6f678de5bb5d3094e1992121cc90dbe96f05e7de6856835d5cb9418a6f6cbcb16b0eee855e1d20d20c1cdc9cfecf6982f21c7e520907146ff827a8a2bd66164c39bc4ec978c52e1ad606048d420daae8d78af3564d25a3a0ca9406efd99afb9b08697796930d854854cc61ff6d00b3957353cb6d7681552f881f175afafaa67760299d654e67d1f999fbe838bdd59dafc21e8a4d23cbc452ac9ff5a6ad4e0223f17493abbdf50f7332b74dfb9176cd29b716a7ff09510dbe75f45f110c54918b98094045cad7f96a5007fda8e31b292f6328ca8f572bc6d2395aa02d4e5962943a7c5c9ad7d8c5ab93c42b8e675ad1bbe90f1962392c830e15fa0db2f6634459461eb09753ea6b19f85fd5e6f85a2f91bac38a1b53af8879ac776f8ac77dd452e9ce258b9c3087a1e8ea20b16b27c8ade881256d9595da20b0a880345e3a4b348e94b82433048dfb014ccbfc2e017de0bed93d111aa59d06d83aa113aaf36644cf8d4bec57d342ba03992990a0550194dbc22bc6acfdd438774ca95aac54cd1f9265bab45812ee7b24d9f2a4cac0449759e0c55a60c7d3c742bbc19102765a6cd4de3773d544bab008740902db491e38bbbbbafaffddc59455fd18f0412e16cc712674c1219a63649f3df898b0169518e3786e40204c94cdd3be8a3a72f10f7a1da3bdaeb66d897d8c20f4237ae6a0f6733b8fd7347915356719b22e2e983439fe36ca6e878ed18f808c39d12b577c43b466389a362c03b9e34f2a1c35af062e1915ba1774a317fd8f865ea62cd25d0611dc823c5df2704dd0d9606b6b02864fbda3d72f486da488a62e6b28880667697845037d1e6bf4b2f5b6d4e718ff7fb02c31cc8e58e21c05e4c85f8474e12ca92b66225348ae45efaf861edab403934476fdc206ac45083fa44d36f0fc6c03dc5c2710bd00819ec52c93d3557c61da11d0f34c5005b26a6f2de39609a82c77b746ebbfc7eb6b688492d6e714553bac5724b809374073a5b98ee2b9b01ee77731cd182504fe521419b05a074f84c0d676b4d76ca61e8308b51c12829c45fd1ff5cfb91a3152ea0e1c584e82453eac619dd12c1bdf14b91f90f2805cb2bdb8655fd71e5f2d6fd393478c934e0eec12ffa9255118538f73725a0ae156cccf7f1d7fb9e8df529e028ae301faf0eeb5766c65c60bf0a7f777203dc337b75ac62db25213fc7a805cea9bd48b1c1eedb15a4a7da22db509088ebe62a3d279981a960b495618f32e4079018304994b1daafbb367ce929782554a6c5c140bf006cca292e4282e03ce803346b7a91dcbdfa7efcf61eb8d29a50526fcc3bbccb77fd8c100d4619118dee883da87f2b5287fac651a6544e9ae11e76f54bf29b44f638cf59ce2fdd47d7c265b69a92c8a575b03d1617bd58abf2e140034e8cc70744cc5978058de61c0d3bfcce515338f17539e9fc1fa55af94e81b9f876ab93c7ca033d0b84c98565f20602c8388c1b4963f5a952dbf4179701748021a5fe6b3b6892bb94c3428caf1c00c1c5b8c6700a12713244fdc394a532ca73751bdf47c2732e9c4ddb6acbcb7e50e971244f970ccc845d307a3cce0cb6990b9ae17321062cf80a876992383f8fe6668c0f146b8cd0a301e42893e001d9ae383e5ade431470d213ddd7969320739d0eec87208f86e9806c7931c0a8a309784b09d36bd1ae12607c60f77b1d2151ce61139ae3c80fbe7b2a5e7a2b12e7d4e7140cb3c131b1105ba17363fcc3796809f5ad042d57e2607ea70ecaf38fd2aefbe5d0bc036433078c1453461dffb4c3ae718c7c5ced7b5b68e7c2f41794eb3499213a772f1a45a9641e5e69f7e62da95ca2e4f0dbf63a8a1e3f7d65aec115425ed2e77f05038f916d048f79b93b86af4f79d2d7e804cdaae20ddcf114da9f7bc208d376e031c278221ec1e8a9f80cd62b5213d06c47878b99b1c421f90a9747e64ce57238d1bce81c8ec6aef7921c251b4c8fafa37bf2e5f99113d6d86552d6309f6d2e226ded339e46cae1d429f6c3d4a6ba0c1b621b0d27174973894703d36be641c81c334c1891c0c99bc91569e7446eb8ab50af194056a29d239ca5cf1a24f0b29a031c8c81212ffa00018db0540641d730c1eac2019ce9af0c2f1ab0274ee827ff9c636cc81dc2fb4d24669b26f7c58c2a4e58e0af097b5d7d18c93040ac5da58dabe13abab9a62136e403208891b5a9590c641d7fe42d1ad6535c4573fe06e94b1532d2ad88773b2866ff12536d20f6aa01df320d09cc25a55f61b6210c1d700d73fe4b073932b654a818ad297841c4f169399ed5e48010c628bee0f50f6d6eb1105e534645f6d3a4d240cf9374406ce16d87dbdaacde13f77122c0392046a7abbf6da99e1f075fc98ba56641d3df92fc1b49ff8c3565a2bf8f7d43124fa491aed2bde6c07c714c64c958a12528fa41ad80f2a5c860bc02bf8aa12e40810c34c3ddad03de247d6a799cd1293bda628fdb0aafbff67ea0616ef344281d64afc13e951cefc492ec66b2c37ceb365f3dbb286d481a67ab2da950db6ec4ab8cd2b028fc6724dddd19a221343e670195e3145a1b9f8b67f9380d9772924f91b90cd29237d249e5cac0186244c2108169487b8ac7d841615bc8e71988e62815a0971e87c847441d29b2da5a86bce51dfbb7a48f6ad582b6a71df219d98d4c0d3aa08cf46d897c049d4bacf45c205f7fc62203f8d296b1aeff7bf5aefab9a1bce735eac81181b88a6ae0220527acb8030f3e4227cfd1fb99528ab497b5dc5fd6108e7aad6aa77de45345e79de2cb9fbc318b8aa08f38e783db293ef42d3469e34e4e5604b93ce838c5592465669d10ee24c3fd959db8b0531f62619281b29c5acbb0e0ff07aabc4d5e4ce2fda6396af07921ad212c4eccb7e60406b1dc3131a57ad179c4c40672fd8162d449c03f765a4b0d08d6347122fcd508a0bdb1ff6a8438176f705bc46bda17ada79b8f3ba4920492b24675fac365998d24bd87e2158adb99cb5acc65a0abdf12a6dc74edf24a6abdb7c479c08c3e2a6db2dfeaf3cc64b65f8bfa4ddc24acf735c423d5358ecd65f24ed610b3de3d2c79768479e0d4dd3548e9a6b9ca30a3a52079d5b39012ca9df22c091a4f97d98c38c3e9087320b5f87304917db8d5001e11bc6f7fbb99596d49dd9f842ce6d70fdbdab2fb0fd6d156296c57321137f4c4ace3f81e974921b0ddf47d421298f145bf7f89391b6a8d391029f928f1677ce6da964e9f236a20fb21ba9b38c86104adc25620be060124143114a05893dc5d96c66d79b2d97473750c9cfe44dd6b279b461ced81f1e42787df7ee01ff45ae8c193c37010ed6582f7f641b1bc4a50bd6bab20f9472797e772483bc2787044727d193215d08cc76427e76489bef61ba8f83fffc087a094c9a08b3a0b152b97e172308737a351e8db0c27f41969a8ea2494d2b0e417cd0bfe80071936c8c1f6ba0d9a712b0291ed799472c9f20003ca1ad7c7f2b48c6770a4ce419f6122abed3ee1de6f928b3e672da04822036fc0722dd36277775287b5d15410ced89040f493f21ead48156a4e230c1e59f4d55ccf25545c7f5fde7caa061c083ccb3b1291f0fc5ae43cc5e6a75c8bad6ea605dc42a125ef5ee7e58a75b1edb230b2659ae392b2c3e3638870574a5ca907084155f29c3ab2875e74dc2f71bf54d186987da05b42a95c16b9ea69901fe62961d2c22523d7d11f257d6b53026c83000b74aa38ff806db8d5ae76446d7538cb1b3928525b29c3be8bc8933d1668b3a98945f959822397db0f331ef8ad9d2e39089704b21200130db0c0437f04939d0bd4e0bd3ee0f5246c6f342566672931c1430f5590a31182a842c64033e8275bf91360861da58ef518315214320b42dda91b44ad99c111740396de7a4c8076afe501d0fc6043b288c8f131c7f644035130b146d0db31cfe834fb02ee558bf036b417efe9ff8953e0c47c15fe28a03ca0d9a7cc7913ed4cc012ff0e25e981775e6a38746471c5eab7b21b6b2e80690d98fa3f10e38e77ce0bcdfd5cd8ee1edef4aaabfe330e7b26273b3bd2d71b6fd72ec73a3db28b329df1141785e20023709e0a79ffed74fcd4a4bcb2dcac2dbbb9f68bf80b61118923749c79d813f12e6c16e2ac1d41d2cbfe58738eae82053ded64dc5133a0d4b2ddebfae368e76e538244fb5aa413e106b07a611aea9b9268891aedad44ec57f389e60f873a45d7ef04588fb12224a4afddcab2cb968040d74a42355aaadfb822e0c4aa288e950edf2ec028139471f155f8ae7854ff3db2f708b00b29e3318bed6ce0ca4d8cef4edb803fd60efd4782371be311d765211c03ddb6a8ba39d7b6687cd749d7bd636d601981c6ce308a5465057e3bdc9d7fc4b27dd6a67edf268e5e373a283208c8a1512d8ca7e1a16f64523cc5202ff449dd31d33cad867f38e484bc2009a60ab0bc4cf07d90924f9d0ac8806d4a63b3e17362f7033d3fd2af51206140c702463b953b382427edc1f581d527ee0a12e9db0ea6502b09b001057869b3836ac005a2343ed774e05dbb7ed99ccf6384a221913f486f884b202803fc39b5d5bc8b62247a29a45dfcdb5489bd751d3608e15ac00036fb3554a63c10d98583823e9304da3f7d1af3f3b3a0a51c1175ffc21b6315ca45deb6b75682c2802a2c0da2c1f0c1f6e0b4e5b0a0c29e7e5f2b56f4a1c57aac698323e03b8e752d446068072084fdeef2220da7369f9d1e23c51511e31c35e02f00b3f2fdc5f649e4388e38ad4a4099f25c6153eb03202b9fad34d544ba88327c020fbd97a4939aa70d9c5b9a5916367d9a88eab32c1a7496501995d2d789fc2b580b1cf86a8a2b33ebe9b12733d8c4b84a0c246ba52a51bb5db39f8d8cde14665b9cf9e3fb4a7b75402da1f25c3b4174a4124e85e1127cdcab416f27d13dee7db22305537d195da098418a4f7bbfd40426ec9e5385f975ffb3ef506b301d6cfaa574f98c3998507a6dbe16a700b9c3240f534045ab9f018b722f03c956afaca8d69cafc065d653e0d8a5d78d2683cd628fe3674577bca78265f1a62a07ac1b0373900defc61ca0aa232ef73048642fd6f6deb4d43a93c194be09729b78a2d7b25cb5686c1a3a1fa28b93ff0f937fe6c096a16b9001b3d6e8610f21a57c1435af76504b6c6167d11cb17e011c6bb4120686835702ac45646cb307b34840c17422b64e3cdb2ce84a3b912cb6b1e6ead4db9704c91e82be1ca3f5e8c76dd822c6a2182168c78dcf9cefff3ff034da1d74a01e86a2c2399b38c13613efbd215c1e5817940a24a7201df06aa3899feaea0175c8d185fb6f82fdffdc47575dc4d8d21a6b76a1d108b5f0de76b33cd9e748e58ad5f4547b634ea4de42115ac5cdf79fe79b66e80d76fdaf0536ef7087b246db57f28700e643345fbe64e5faa610a44c7bedea1ac67dc93b050799ca452c8bd3cd76deab8e94e9cb1cc2b78c1e2c44d47d46c6f97da4d014d0570e89f40a73b253b2b180cf9eea34933f1a42f729d5ca166d5b4624224ef788097797d8ecb70c64fb858ec050bb51f04a200f4394ec81015dab6eab37fc586a5ae178eb7b328677cdfb1676878ac223d08fd8d42d74875d3a0f6fef26c3f5db09d3dc2d819822617831fe0d2ef67b5e972dd32f9b85d6dc9a33d481420b011a4b9b5f40afdc778f0b2a42a54d463b4a57902674db36afd270854b2d8587eb842aae0f34c0801fb217523a0399a56fa786be05c5d7298f4905d0d9ef8604d0bf6d807d7050b83d4366404f80b059a19a2dbfd9c7347935dbee924dec3764128de1f0107888ebe92a010a5b3ea8419f694206139ee33a359bb58fe918ec630c36cc13860af59e39b35345e4dc7c7ae0d401e1d173c1c0a8fa1437a325d7639c2c611c2914a72d8247b2de95d7d79e54cd57a023a7c61f01d6b6be2174b6d207f46b208bbc75f7b068786cfed52d960caf6d1d9e964b7300a83e639d0adb4615bced06496355291d34fdfa51f5fb96c7a1ff6d2f232cc71dda32fb695eb936b983be0e3375f7799fa04ec76aca21bafea3b600714b470947481e8ed7292191ffddaa581b0ca3f32d8f7b81f627f092e4448694273cee8be594b8b962cfd45577f2c28ef1bc2e93bf1f99a44c99aeb1af7f537af72283f0ac3b7a8439bca5365baa2dbe390327899950c5cce3fcb602333a1ec10d799c43fec7f52e35a95ded7f9e66e2815ece85f265051a54c9923fb54b6d8cf76bb14a8e4d1bf6bbbb15113eda433f0bac11b9075341590c7435548dd449fe090246be7253f199ddc65aca256d0f5cc73be221e650f7f49d2b3b185c8ee9a41e238df4c2dad9fbf339ff0888a26e9d42394a1585e49635ebe7c839b6e242be666333518f2f304a060d80c2f4206f017fe92bb0e08bbc778aae7db3ef1e4a2f66f06db8a2ae77c3457bf75fd8a79a037f7362d140ce21a2c0b86c3490851027045c866c7946dd9c8df5a1a090d287b57c34692c784df2154f5f4343432ca2c0c3790227210c08bf4b9e12b9c47dad1fd6da8fdfa674058ff56e0b8ff59e2fe42f0775000ad9d3847c64ca1dbdf3773c90ddd5264340c03bc5343fc2d6c8e92ae4bc5bff20ff4837138453ae97e9631a4fe060190a7b6615fdbb68217b1fa39212f510a69048cee38eb0cccdc691cbefe5f21a930100d3cf1a38e37f5fb6cd1ef51a5be5630a3f7c80dde57fbd3960a3115f5868173990f29e902dc50a79f8619df428d0e2272d83c44ef24903a0e2c050e62c0a4c0a202eaeceb7188abce3fad93c61dc6f1a705222f5164ba5ef6649f8ff616e3c415c57e0d2bd3ad8c6429cd2cf6cd8180bfd6be9ef1103cda5becb4d3eeea4465cfd230cd7953d7fb4807c80ae08345766a66b5851649708ba30b4a06df6180d34b8b0d071c97df426df0f9935c0b7346acbe293ab58049c829d31c01577cf381a7b5f566b03dd6d0715d6831f4e4e5f406e0fbba22d9d89ddb4becb8bde8d5a27f4d842d2ed90c5a85c20db9a4f58c5e5c434182024e5a54aee961a433b6b8f66cd7e225b47cf1b5787930f91ac6fb5a365083d4a5b526e013c7333c45505a667189f2159360fa954a219cd3748905994b40d4cd80c8f8e40e08f4f9341bb308af1cf17864b58a39a7b35ea65ceb6c3c8ff594cba05ec20d00d9f8c72b2c290138ff04637f0759eee2a5fdfacc0d065dbbeefa0257df104f075cfe4426244412503cf6c59ebd73a1801dbc48068b53934835c18d09cb2786f0979cf373f11b8d424c8362b3e1d3ab7b85db131311bc8660cb2c9109794eb2217ce5f1fc1443b554b490b4a0e72e77b8872930ff81dce21fb1a674216903d4b371622e6442a13409c0bd11bd92d33e290884a76d3839e559ff03f911f0e4896ee4f0a89cdb3190b66d33ff1f1c1e47cfe83c0036694b341281cf9d511c9b03328911378c0d97973d8ba454e0edfd4d0b43aa84e17ca6a588a24844141a81619fd81fbd604119b07e9ea0403aa4eef7d0c063078ccb8973509a40024980a6d1ca75a0cfe823a319048789e7665e87564efb2ae445890b21f15cb70b3377f808c03f4c8b89c1839dba0ea7002ddd0c475a743001e8a37da1e1afc965d8bd9f1f471119026c376cf19ab47233f869591a952a17ff73d21da7afe8ea000d5c6d0a144daf71103af1296f2b87cd0b22a5d0e8130c31c6fcc18d31372a60cb95e14bf2012098b5b67957529bd8a2b1d1a4d40b8db5c2c6bbb29b2afc3b76fc9016a2f6e87074e8eff07e9b4c08d57eaadeabb93d732b89da48a7b252472fb2f1789a5e9930f716ae91036ccdfcac1df1920ca6197aa28e2973f31db4af6a1ccd83e101eeb1d8d79988a93848b6344e827a14d25e7ebce216dc2ec1ade38b9159c8e69d3d6a13db3b1df55573714f0eae6dc463fb958dcc4b02d5ac279c89d186188b7c9c99309d0a8c9eafb8af5eb2f6af9a325fbfb7c60e97484be9521577a4676be05c0d79ce44a9d8ed0c2bdac3da2f641fedb2f19229400642ba4495247a3e789786420ead4866ef95fef986060b3fc4b143af898672f304ac2813389fa3554a1a893645a5a2f1362d222a2ea54603da34763328b29419a96f44d51684a494b6c55f87fc59b84854937d0967cf11f05c1828ad619d484bb1ff48bc2e74c87e312e61d808dcb87f83719a2e06c9cca82b1628538f32c052807aaa25b43e7b576db7d81cf0581ae135610f2f3afb5efea13430c15f6e609dd63f6da2300fb4c638b06d99ed6e08993760d5f3ecdff95d4daf46b5da5a15e4c3c75d7a2c45b5b283a21846b362ae30530303555f23230db6c8e52630ce9bbfa3b36c83fb522a4e39149e7c7436c5fbc187c5afbe210fbd6816037efc7b7842ac98a1c85a0dbc00c0953321cfe09cff0614a704ec178f1d5657fbcc756e2fe8b15afb1ef5799d4caa9fe8d607e0e053fa1f7639326639171912010ac043a272f01efa37adc6793f2ab99aa8a100a87537917e1e26aecaf520c72973c7dd979357a11adae0557f1ad32166d02f4c3cb60540115a2facc1706d08c259506f409edf75166fae058c6028ba4e2082fe65f58dc1c61f4623a44519d45a643e903a60cafb43eb732cdc3cef52467c41cb6d2b7c0441b2006f0583cea2ebae8faacc9017018ceaa16908bbd3c226805aa07271cee2b06a438ccd47ddf171fc5addded72be01916ecb2a3c97189265f81a77c01317469a1862667eca58194c896647d53415e3ff081915f87d015d63510d68b7da35b3b94eef58ad5add2caca0edbce947da71e294ac5fdb760baa7f868e2a48b6440e1e20f202a1eae28e58dc8d6b4c92012605c7aef6c53e74cb3250bd6a3b89c33f1e1e8e3e3a567c0ce30d87868a2be2b57a4793764fa307cc851a6959eb297028640fbfbccd9bc4720c17f47d727e9f178d23f536730c2cd7311bab54cb2c85b4195452f6ba6cc30ec259cd4effde1ef6392e17488b80ae91d37b5361650dd99e5128da9cbe5e9f04549f415f7bb6add56fce976cd6e66cfb61bf8df70270d063a022961ec771f6670a918ef1466d118c280c5b3499c3517c2f27e4b5430da83013234c1ac70a2f7850cf92139208688aacb214d98e2c22d1f6892f00fb3701d407cf7cf14cd224d9c035015d176a81c1677611efb5bf103249b99304efa409cb8f3b8bf481515f1f0cdb6fca91b97fb42cd5bc9e10890be11ec26af314536503e5f71c99f79a85ff502725bd714dca94e7a2141d83cddf7b967f16e26a6abf91f388c154b1066361e510aeb97b8a604e3e47463a5c6996dc09490d8f1f04d9b62d98612cdc76ccbca9da372a68baeda469f16744bd25701f9e3ca9df8823c94b830ea37f49e2d2c4708311cc7e4472770ca022d28a15a0243c4d92436277099aa9bee1a741a2846c342d2c3db421bfb3ff5fe250163bac3d039eccd48e158e7915180c769d1e08b4f5f87fd7e707621f77a4098765225aff4a7045f7db2dd143035499e9641e7390657337233a5c24091c1f060f3482c79d7ba0984d12ae6e66100071b8ff20873bb3a5190e617f33aa4e64490c67a00c45544aea12f93f53a1fb649bbd63d6ae2ccfb61efb1ce675bca018360b7b1d35ed377c4f90b90ecd9fef845f3b5466730f665ccafbda6f7708a95187ba3effd497fdd4083ad19e4cdde78edfca483db8568b64178d5f410760b81324bad51f10ee01d7a253951aebc8d8278dd8b44b192478a7065e70090801d34477cdfa65cb646eac4a55433ec1f016341784e4b1fdd59541f9ae7884a691b8b130a230a5986d69f521d2cbf91071f150e934bede9fcf354d9ac8829fc00d85fb88e16ffa8cc5bef5227a41088427380d6134e35db58840713fcc41d88b10aeb638280979acc08bad02db76b4bf9d7abc0e31c78fc7f8a3efce85764ecc6e1b3227cda783851e2064bd9a0bec6a4524f57b5080b7d426ed2979c43104bb08d3d9d0311cfb0ea188e0d0e221618162173fc92290d2acb1e4bb2ac9c34ff27918a39cc7015896ee65bf68bc0af5a2af2cb60f730a62592019f665e27b3d80fce6ba1b5bbcb8afe7122c3bcc26b0011adc1c83241d35dfa81996826b146a79f9036c900698222481f5fa46ca931d120cb1072296b6c148cf17c5c8aab8f2a1ba5a1048b78b4a28fa809dc8f8d95fccd45d792b25b6f337a5ec7ca6875f0b265ddb1ff27ed28964f515f7809dc7804a418f319b5f862f79a8952d9210347fafcea8e0afef4fee2c8ec55652206e3f54c8a6ab48710b7d104121b207a0860b4add32fc641e7bdb501393e12404e7ce76541b6b6819a702c4b92572847a44e24cf5f7a501c2d2e0a7dbfed2370b659bfc7a8472d7f260f7c57409cc6bce8050eb70ff807df73dccd2535102f827b6917b2c39531a1e1e2837135df20f5570eefae0486e4ab8c3d86b2e96d86c6b3714685b2fd5b209caa532a9204c28638ba3b07f787b5f1c8249f5f067299bfa9a4db43b7807e0ccabc872cc2f9cbc9dbd4e03d38812b31c0a7ce41305c41c449358c3e2c6c5d637b6a25b6668a29065415e3cbd7e8eb12d3b18e02d2807e05fa6b933fbf6058ec710c4e83b16f1f40d90d5808602ae1863c9a5ff01ecd9924730c638934421dcbcb70b96ded192744c4a1105e99aafd9223ccd380797b16d13fc6491895b35c46cbd606dfe5b619c9290868c9f9d4f06f2bffa56a2db8239fdb3c4bc2be344a8817141d63669300ab13d63c169fb8ef6f4c740a24470d6882009b4045b101069ee041c0a2c37132f4cef96e3fb80c2e49d7acfa7e42a9fa17cce7c36bdd982b85c01a9f1dd1bf272b19823f0eb063f761cc585251a6eb8c1a6e209e47c1ece886da07fdfe2a3083dd93202eb4814f6423596d2aedf5ab8d88a128e8224345b191a7987614ceae57b052407ab0a7e3879e865cc5e63450b2be92597e8eef43fa7a1466a63a76416529ae936edb2d74a9da159d49409de301d5f2496d9523684a75daf97ebdcedfe5ea5def22b0b5ec34cf29c07e079ade786d52b587a6cd31e905005591c38213705b1ed561b9ed7dcfcd0c01602b54dd383037b41591e7b068c24d28613e876b73f3f3ff61d687b90e1be028e25e9e48594fe48662e16610261b22100a9826b49c28285633ee3aed4a38f7fb58cbdc07326446822abe8d8950d91fc5ab448e8b2adf956fd653e3c7781717550d39cbf048c61686b168e2fa4e2b4fa761b58e6be0e569a0e440b893746fa38ec687201ba6b6bd20082b644c5654ad770692e68de46858cd2cd8c92d148cc3ec563bb559c51dafa1f24b656b32e371cdadf613cf0af119a579020fc06c953705e8f24985c417469e62df893a0f89c21ad3e4b9f306c525a4f252b79f68e1cea9073d7efb385d2d6bf7b27d9199c30a5ac17a2c1e76f0884241f11f6d0736d570001d014ed25812ee7eb2f08522148d621daf9b1de6908bc747b239b4a83974aa34b4e9419074c523bebbe55025b9bcdcf17c6920f9cb2d97664f9cb869fcbcf876b3305d80e43bbcfb9ffb30ca590f43b61779156540008d28a9bed439dafeedfe11066c38d722fe32192447cfc1222ed900fde72c591d574b7e3db9ef948d7fb946cedda93792895c9ec6102fe60756ba1172737c3a965dcd94dc8d9e8dbe104c1c9c4027ae62cc628a4279c2549206614e79cf9e55670b2bd98ccf16dd53b3252f3e311bfc03a66ab6b8f1f91b01bb59a1442c8589d931887126b090024174b8b93875667f02196b43543c2a6d5e072592ee220540db2d1342c97e20cce002b57709ddcca03b2d5193e149d2f57a1f8295258437b23fddc7b13c3944873f63e3d5d602bd7b01a0530748c5cebd7100f2b045d975eb136b5aba83db7383cb886fdfb15a2c5de640041441cddffd7a09037839d1c1c17fa8755dc94142da1758b41c381cf66fbf5f1a82b02f6201b4c133965c00411b6a474bb2243dc1d330b4604553e103b4d4da3f1eb1a845030bcdcf7bec681e3a17c084fc5d89a00c9abdd2e05ff32b61c0fdc542fb47ea779c6079a85e48d8d90367906dbbce5ba8ae806b7c8e08a8e177305260c6bbbe8a9e65f9ee9d64abe3d17cf5f44124fc00566611e581ed52d1fd7848561f94f6467da26915a2cd989b1520b26c94bf5d658b488fc30f11e13ae8d4880bc19afef6b043e52dc981ac673d03ad7e07df7626b49acf30e482386ff0d69a1622c78a824aac74dbe6cf92d484a10b5e71f4111a08fa72eea28c223c897e3739405dda82aa95407240d70d64afc2dcede20518c4df04b9d52564ae94271adcb9df36f09d20312a710d300fac4a03cf9cf6c640cb3d57b8239ccda8c996094009020186c477b37cc91ae826f1c86d6e508221047b97547422f340abd854298a803bd778abb4adedda4afd5ccd64fc6638dd2846f57b537dfe5021f4987b060535049d50dc5621a84beeb2bd591f1784a435ce0afca44daece6add18ed035bec7525f4e9d33d7d730f3bddd6458ccf9b9b1ccafc66f98a9c39c3dece0d188bec87d07f409c660a88e4181f804f81ceceef055cf04a4cbee340bb2efa8435f4de78d8fe272e8f427af7499303d5dbf13b46eb9664d90d45d06fe3c4976bf4a82883a05bda4a0e8a50732cf97e7c4ede47520fd52fdb8050e376cb29c219f0e0a732000574b82f0d37607edf1547345559edcc8e20bb9ad7a6f495843cb173b69055258ff42fa0f52080d2f7b1b6978f32db0fd8c52629a97370301f2cd67fff8ce3114b0de9304d8060579f634a38941952a6d76cfb66a9b62750c2c09894222c03140412086261ef8d292e8cc123abfed8cdefa0a535755a04a82bf46f33883800705baa233ea20df43be3ddb6d5cca999f242044e0244337e2639259fed971979017f668bbb0af32b8247913e5501346b82f254ab187b05e995705bc2bc828b3fad4c9310cc31620ed9982e8cf3132936e5165ab362b89a585e79adff75b90a51ae304a734c64c141d57062dd5a6f0ca152f85184f034c0477ee00c8296efc084e6de61a5b448c33cf220c783fe7d35e4c7826a316d005af6e5c1caf507949f637f4103a82479a6cf34ee6a7995af9834d84a3a1c53a740115b048f70050651d579a4dfd570de1f962e3caece822e82ce422c0f7da08a0f4afd60deb2af512f76813769fd504c67aee4aefcf0c912df44868893b871e67495dda5326e1eae0e76dbe47212b3690e84bebd63f744a2b5d5a4d0cd3143e1507696173654fdea69750f4fba050daaf1c8fa4ee320862f17b5f438231c80a6fdbdfef74d1186c0a24328bbbe4627d10b897f7f14d83ecff31257c26c12dc3a9a21719a0d73881e5fa292036a4f4a8fb9524d4fde37d537fe84df899002ca835c20f9916f71a1d1680c9a2d3c67c82e58e726e51d098f35a1df21aff836c79d22e9be65fabc12212f097640041e428bc8ce4a82e7a69f7b53ff26e4b1580ad53b8aa2f5b4329ebd9887467d6b9a21036e8dd77d9a9acadeca2869db078beb361666c722aa49dd9ecc67a005409ecff63cfb7f4e6340690f8b371e3f38b9ffe075767c77dabfee872b293c510964f03e3422940e8c852503c317213a71db1b221d624c945e867fe68b2603e0575f2daba3cd47007f532fa9800bd401dc077bd7d03201febfcc36779847809a7b562944b5062b2ec6ce0b04ac9c80dabafa5b0036250853161bedaaa15fd492272c7ab2207910c5c097e8b8e0c3fe3e2fa3ccc5f0751abff7ee6ba9b8fe9c60d20e8fd933344a77bf26cb57b2880cc51808bc9f88f205788286891dbe105e8d537cdeac91be939bf12b19a1a3db727b3577541e938797c64bf40347a8e964612f80f26faf46617247f5c54cfeeb583dc016b9553910c5cc04b82783052206e71b565f6658f424824fecc121f81b0f11d52dfbe3f444d8700cf999c35f0296c881346b5c1e0872cf1b7c8136f4c9ec07a03b93cdeb4ffca0db077d159b4c4b839e39d9c2f30fb3c958cfc25866cacb125c2f73ad1caa7a1a3d4685ea0a8b838023055ed21947163254b7568138abf2d020ea42fe21d1c9d0e359b08b5553d9db4d3c910149e3666475ba60f0ecc166ac31b778a8684d57199b2c06ff91fbe5b1fafa934ae0e6df8372deb298ed222965be7f603edeac81b2ba8b20f62ab6c1d0d2b47275a9d57073e5bd206c1663522bfa69e9a0951ca8a21d79a9321ae6bb5ca45cec291bc1aea46d599ab02af85a8da39cb8544f07ca1c31e475d96dc0b997cd4d24ebf95e04247b9c5f26fe34ed8aad83b5f465ab3fbdbd2dcc7ad1e7702870d8d2b40876e8ce9c2d20e304f103c8449f658d5a3fafb5eb5ab8aa31131e0ce79995eaa863d21de9d13ebdbe5b727915dd3287df9ae7dd884270a29fa888f7b0b8a061fc32b7bc2eb5495959774f5c30b290664da1e365558551e3c0c2a74209ea3978cf32674575c9acc84f84b6141e651a66eef69b6543947ef650e3c6ba0efab0261527b3ed8c304caee1bc7ac1dfee837c9aa91b44a71f8c0d42deb57b408da8b99caed568bc498efc2e9376de2481203a50108578d05184fa7921c8feefacc7b46f64ed8ca632589daa7cbe110071f094d92668c3232c02552006f41af5e81c0d35c17833cb93a6bbf07ab652923a0270c9947ed8253a567c57d6001e991a30762a505d8ae0cf6771242ead78f189d960bcbb2a3505cdd42e43f9559590b86cc6f5e99260efddbcaddd9a18f39914436057e0e9d5cfcf2890784f9ab6202c24ff5980e9693018176bc5ab170b871096188bf72640f6e2c551c09af6269057b1ef51fb7800fe014161e1a582572555b546b9e5ef6213cb4e706d9ca8e1cbf20f224fde1ca840ff99335397b84c94579a66c23c99c190a826901bc9d878f9c94112a3e7188a1d33f29d529d17d6a20960ddcef2fc308b32ac94c8894995864a68b63f86014469b509024f4e723a64965a6ecbbd9a0021212b40f8b382912719e3af11191e6d65a2d371c14f43bf8db83270a3958f56b0312465c80e4ca27fe56c85c905c53eed10843e8c5c4178ea130fd9cd4f3a277e027dcf204056f3e1c958729d56fca40cdfa2b3849224fd51cf660d67a3c03dbdfcf5efd74e25d400e6b6afc93302a76350898a88b5758b8653484d59bb319e735c1e8912f31f7946c960b35f09559f796f6f37fd077b8b69d6a0fef772cdb79044dc51e9c9762b4f16d4f7f48be23dca33a49eb5368b03d9e2c382ca9f10a92dca14a3e7dcd059dad84bcdaa129266c0b100ef1ce51f8d4482d5656a78f045fe5ded5f4a56656b9c33ae2eff3f8f6eed20e6c624a5269fedcaf62f03c8e060c4a35051caea1100975a374577637870ab150e62dba01b0590b4dcd5bd96968d0d23fd4e3bf2000c908d9a8ec69f0fd2435afdafb9e4e85ef8adc399f3ad0d28363778f403fc95414aaff0a83acd3fa4715fd053c000d39ebf11beaf67c2167414d8cd1bdfef372aadb828badab02f77288035e742ad14580265483049dd210f59d225ac0d059ae09468142ff51e35af259a6de8403e7c805af66513e2877996652b9276921684f6d51f781af3a248b5dc9dc2a61e67fdfee89e6c04c6814986682a260ad415f79e84089e09a662fb148ec6d08faae45bfd3ccc95997550ecdb505642f8d956840a4c4f546078357d56f3ebd03cffe78cc536c41e5638054b986c59424e838d09905c39ee888284b045aaaf5f92c9c4118d2ba34c74ca0b38336c51c0d3f7d1c9ce0316d01320fd8499247094f753e30bb88c418c6d4c9c0a403cc7971fc181b8eda44a5b9b2acd907b1c499ec1f26b8fad564b9b91cb219ce92c29fff78b643892c59a43a48096a8cf396a061d4b4a870ef7601fd01348e7865fce9c12ded0b9adf35c0c430990b9487fd39f79f7c95e23d666cab373cba680e21b303ffad70ef1037205ea6113744d6ae806f06027db1a69c0f86e26526ba3e23c3400a0f5f5387a1abcf410010b5382de1abcdcaf23b6c4f218c4f0f2a73da7a2a21d369038ba6bd0204c31d015766af1b3172d06cfa2db5eadcf23136141ed0b1cfe3054625d41224c038db44d9926242effbdc7c644af97f120b01d77c5919752b5aa2f9c0060cd6ca6da4f843c0ab870f0c21623d9198370a49bd4f254655547baf6f3a67434145715acd2dea9b529a6f94381650988a696279f00693293d42c212f1f849ca3c40c04587cedb3cf43e8d4bef1a78b2e3c14d8bfa07e73ae30a69881ee5c7f408548ab4a3ae0475d217115d6010bc10a36a4010064caa6e283ff3421c9dd0ab8603c222d307aa0639423f151710276e9fb46aaacc5895dec8d23ae51089379ed0fa6731cc931051c96da1774947d3b40caf09da474f7b838a4e8cc8edafaadbcc2569149db80def063bd7fd9fb187572d8ed85df029970423885aa8a5e0b72fe802425921130713108c93ed7c1fbbe3affd3e26cd0e17cee19dcf68fcb1f813902cbe8b877a73e4dfa9adccc028840d273084f4c670b3a878e3f00a253da0b843139e06b1bec76c837e37859c295ee53eb5b14e95545f5ccbae10bbd5067bb848119786f8a1e409dfde2166dc600bc169e2b7850fadecb4ffa4536ae771d5cef7f3f20bb67c1176c68704df0373b091a2188ac9a075c7cecd41c2e888ccac1ec801df94d49db7c11a75113df43bded14da8497d3ad4149e6ecc64e9960a9f8608a0b251b0f9067cfcade1a762477f2122d6ec81fb732e76ae957ffacf428b17f1f19411a0ba92ac10681241f023a4e11d1ac9b1083fe00e1398e7e1d743800da0036e9134596f9db6c0410348276c3705aa0dc9e224da9bdea2a25a7525e73401259d36ad7a2fc582abd014b7af8328986d8c2e4a2ec824b20fabea2282dc99b2a2396ea4e481e785a856e042c87d2717c26d43df3c1777970151caec9506774d09381318bbf071a867f6fbd898065c4ce9e7229ac1812de3d430adb46e7febcbf017e58c53051c1c0826a03efd25726fb2f306f21d8001c97ba0e5002a6d53c8192861dd5a5ea98f1dcc3bef46f54cbdd1d27ac40a6cdb3f63997710074ccd81ced18f984c9345dfbb9108034fd9c98965ac9e648be99dceba1a62c30c4fe8083c361fb704b27283c955e070c2eb805aae6f24cc2025b2622475c1b4b3987467cfff5aeabf58682fbbc734ad1978d4888010cb14edebf54b22df74f5d8eecb5f9d5824cc2fc69c5579caf292a91a55098f1a296fc818b47fc02dfc7f382e5128ca081f5af2ef145068cb8ae5a3c3ea14184e3c09b916cbfd51f29884568c96c920b068f476f309e49a6d25253c31de41300dcffddea796b1ace0ee2557641002a15cdd0247e40567fb6f15e9acbc7e135321c6dcfdc352bac96f38d8d3481cc94fb3b48688db46afd366760723cf1528c52febb5dd91bd53722762dbb67cb8c6e74592cc544f9c32ef57c5aeaaf1b56deec51ba1f550e9b104faec25a8d13a65b881c19fafccbda1691611f04f0980cae9b22c60cbabbc1fb2653010a71fc00aeba0e69ca5dc9f84f9f540021965107069a1c4e4e945a5dc485a83d3b08bac7f708beccb4082e724674bc7c1fc8ada39c5d55eab06a4b50cb5201b59ecc7fc9a66748c19f72ff1b90a6c3dfb6af42e9d9312ee3ecf7b968da406b438e8bb2b0b806866a3787727012b2a8b1820ae69f6f71282648a6bc71c198c431ad10fd511a2326a32f3768b1680a0f0286173430597f90a4f8b2f1181d378166a942a373ebdb8f00bf6086b00c95991ac04001c949407ed202334505a44130fbca181d82e1b1447903f753403e7bb8567daa15515d22690146d9901f337cddba6e9a28d29bf97e4a38166cbf5673296fe27a793424c8c9fdd67006ac3cfcef495a510a5de0cb27309fba209c9ad96b960ff9d43e36f23e8eeb925f3befc264afa1e2e8465068f904941ad9cb5d6e2a86c011076ec5e9d3252f1fdd7b469b1b43441b9e69d8cd16dad6e4894b7a1cc273737c60a9278d217e87668774e69a80a8842c1443ecc99dc5b5e1fc9bae4412481b9e37d3ce9c3b1ef8a7adac77ddf92d70b9c63b2b19042e99f95ac7f7c31a4d76ee7a3af7d8fe0209f4b385555af1dbfadfdaa6fdf5d1f8b06fb430bf2ddd961dac63ffd926f8a7af73ad2c12ceb7b8b467318325d31b1ada0bc99461845e07a4a087216862e12e3b064a7516c546a9ca3fadcaf5ce1b405036ae3bb26024f51b15a89da0f56ecf3529ebdb30eafe1d0d2dfea9e2332cb9845d9e4df8c1a996a4b0c09c2ce79b8bc5828f615314bf4f99fb1c40011a978f693642aefc6f977233362c0a016022d0663d56c7d386ecd6a5bdb9412da4d0f765a502c93991b65a3a27552dc4999033b314bd7a2e9a67467e7762008b97d33271a46e9ec87bfc2209c70d8f160e012bf6bf2d1fd89db475d0ba61b5971bc962173dec0ff60c4b3fa6fc03b5dbffd35e3d878b25df068e6e7a9a93a51717dd909c181fbbd1a2d7da0c2a8ce3da43b7f0559294733f0030cc333ce90678384de7d9ccc48edf2e81c5b85fa41c840e36a940adafd082c79236e1a638b4860ec2042b034c0c14f19273c51be5701f80cf7eacb837289d2f060c4b5cdcae77e75fae91f158007d4c3ab8268a9f05a1c7d04ea30281c6d48bbb7c661a58cec4fd21bdf176f2b144fc0e90c568419ece3d919324e0704a5840e7edc3f94716344143672bca6f4efa1c2b102178c471b6f0a70716c13f6a8332c4c5ce39adc40eca9b896f7c53b44ccf453d6fa9d886f30286146d85115d05ce3fb75c46515988741da0de2cf37072343e4e1d022456ba934be0cc9f7372055a4b03e3d564dd0383422acba50c181194700e9bcb1ddea231ad94c5f24eb2aa2785ba5da791cde892af840f3a5ac49e09ca23fd444cc5b54fe33497c471d0f2d44ba3270221a0c89dd49d62f7d8fa0b8932e07bca1c9ce6c6713951d007c00194c6928ead4f5f0ab9b19c61e207504c5d0efd039c6776e40c21eafd831fba87111e2475ca5d7cd6c05b5f711d6b8082d871ead47889b3277810b2bf132b1c9ca8b10651f106d32162c3b775c11ecbf70ce651a35fee01bd661e92eea6b8ebd69ce8dd65571e008be0602c11b21c2d06ad4a453a8302c2494afde644a87f02fa76e521119e84f07b068e70a0628b69cdddb43ee189b287e1279034389815781ccc409029afcd604404a3503afc643e25063a35ecf633c35341a2e749d8fffb5d7276bbe1bf0880e690b0aafd51023a3d2674e19853ea5469ea940eff772eca72a9fd0fd97e1fa347a7dc1c6e2e7484c8f429ade2e2fa2860f2f2bc96a90a63db464fb15643a26ae715a668c9b3bacfb250389e79443123a9b87682640f9382ce02ebdf0f9e2f02e5397ea8887176b0b09263d07f5ef0fba2812e32966d231983011c0c30b3d34d7f79a27dac6381cd3bb7149ee4046b705a0015fdba5a6e571a24bae973b5843c9d1409119b75727036f817217b90245b44dfc7b00d7f407badb370a14a37a0bd7c33ca581bc2399896c57bdc4f484b7beca513d4b045027fc81f9da42d82adaf1797a040f229d4d802aa7a6225b758ef094f750f0b2ae5c11219a5b69cf0a7da9ebd7a94d8976b2febcd92581740b8587f19c21bb6110fc0ca89a5944c2d8d7e7fc3feaf9242a2556d20a016ce594e7707f9ac69ec64378b132af8f27f3b86cdc8007ff478cc4c094ab3812b9c5ce8749253ad0ed192d005b0e8adba1ae206ac7d3cb6f466a1d9f29e20340ab2496948eeae3a8fc5a7db389c3813c1df1482d085e5bf73c6d0ca261b7adb4c26ee0e8a631c8448876ab88a646aea9a603dca7179d1d174630fbf1462dd48f299a9ae66fd348a8fa523e88750a1968399a4d66f6d33eb3d02ae01c02142ccec9db1d711396278f53e56ef50325d1bdcde5d69be0a9940b07fb6845cdddebebdbcfcd9b76acd3a8417e02c05436f4f6fc3075764e4c6f6bc4212dc2b18c67568693970bc151e93754615fe033ac13d8def2fa45e533b06d7cd21275e9cf5373c55804c2a87989c9fd9493c4c9ba3694073ed471c4369fb0d0fbb3e2d172530021d95cb33ce0014fc2e3aa9058a03788ff41f09d2e4d4517391622332646ee512260ca040e709d1bfe3fc2e0a68d3a8e737338fb905524016515407f467be469b0aa51781988de5bf4032e42edc8ff996ca4591442a42b0e40d58da1a56a4a8a9ace3548874d7b49165e942589bb06d6d7b26f567ac4210559deb8308af2a7b3022c9c8a195884e49528143f9212701235cf988942785e855a8e41492e073fba43585506d0e4d7f554542f86bccd76ae56b5fb3c9ddbaf6892bce9abb66f3a568724749dcec41e1806829751ceebade531c354062ada745f24ed5fd0b13eb8626e8491e8078ba60f35dd0ff67865cfbb2e460084407840310c14a898ff0f36a25e43af5c2c4e46f03013a27ce099161b750535c93cc68aa4c12e46996aa581d8cacb45e870252e15b0c8e527f1fb5ae3420bdf29ede84066c002772652990bc9f071affb32c0a02bb40a28a8407b8b7ecff03ab215b57b0c57d0d59a40d23bb5a294ffe74478b85d3fa680d88568efc0654226003b117b901cec99bac91988e6dd65b7468d56ad3338a6a38cd1a03324ab51e935fd8bc40384549078caa5db831cb5ce71c32e9c764b07f28626214ad32d7650f481fa47e80e5027625334192ce90d5a1501eec9edda4f29bc9b3a54cced33eb23887e5bf1d44472968ef897f4a29d8bc211f22db6bd7283768228b2eb5f3b586db4172fec0fafb76dcccf3f44c91fe388bb46bfe10c0c7e4ca91c76e11133778bdede37ce15941d86b3e666626d75494bb4518a70e702c2942157056187756115f74c49006d2c932c50b0aebc0b5c80aa56b94095b910ddfa89906ed8f39c244b18b2b2be469f2b27be0c92ea5325e32c24d6a5e85be2a6f260989a55973a90514a6be849e7e55c09909dbcf345ce6b4031d968136da18888db1edd66850f4fa6188c5e87cc1c26be5252daa4c240ff5466b03d0cff5159ab630cf66789c982bf14cfdac499f1d60d25a827316c24d5e215664d22f5742d4ea325fe2109ac17efc93dad8f8c79d09d72bc53f1e855912df7af141b53998bac7d482617a0e88b7d7dbf9a681497cb6290bfff025d81371cd9ae807bb18968319eca667947f61ce9b39fddf07bd5cfb5becaadd40f2b63b59b9a902056c1a92aa891ab742970ddf74d910e445989efba219231dab884dd5915748b8584b612415ca9eaa9fb899b516658afbced1ddb1770d06ad01f4cbd959882859b0b610439c7b7d4d649e31ff5ae33d6b23f69dfdd7edc074fecb4d1763e358b5876511d61a2d4f452cc71c995eb20064d8a5b34d11ec134257ee48b0a15e4de74786c593eda261bc2237a7504b3eda5548c4c207664f4a9f52a4d4470a572ef83ae92b80eef5d012aca5061c492e358c08f2a19db7414efd8c45cc7d3f3f0b24dfdde9d6218951c077de9bfb0c2e31c7818b26e5e41f61eb70f7d48dede945ae5cf826b8f3646eda8bb6a8bbd5f808ed61a02e3742927aea9d25be97fb54e9e2d8f7b6550ff7b809c0d941a4cbf42df8bb53a104715972a9da4193ed9175fe717e49db7e43160f931e20fe2316a55aeafb0193bca096e9456c9bc78d809c06837c1b4520d002e1a9690b310206a40238d25e06e11d81d7b04e06371ced05a0e32667d359812630cbd7e3757b2da8ad66119a1c28ff2cb16c10c38037244abe64c3bf7aa0be6bef4e299969ba85c975c32acd7b3a0ad3f6b22038c895f4b2523400e6dbb9de42749e37434b401a8b122e0e6fd773e5577338d07ee072bbb2039d8134deb74439a1eb3bd1bb0ea9944b18f0b6609fd8c98465e52ee01f0fadf3019eafa649efe181c446c9150e3e886fb82911f7bc636c0fbc10b8d75ba06b081a1c4feee51c4b26f217e083d64a01af37e9cdf8a084f7ee3885871bda0a79b9fb694eb82ccc53e00f7e67b1019e3822b2b4f511c921dc1677c9bd029db87f269046162c6936c256710cce67312420a4e5e239c56d697b797e983219549cf1b8d065be26d2fbf628ec479270e3cdb12b764fa1dcb786e92f50460f93456581d749905bb6c2dc06f6052636107bcf66ebafc6ef50ccd4b2c842ea212517e06fabf9fe15877cfb69bdb2f858837bdcf490bd10df90d641df20987b754df57faea66b4d0ce4834360fdfb432872f1749d9cfd819be7460c2baa67db02f6e354fb286733330e6359577d367040aeca44d467504edd1cd80850229991692c4017fda8b15dc0dafb569368223d5b3c9be4cad9c6f0e53bc12a78f6d8696c5913f35129962f8a70f9c585dea520f0483cb1a8b62cca4f36adc6a1308d72298feb2abaa742ac7834a207dd01df8182fef6734dd7abb83cca48f46aace5ad3c57848e53174d254578c8a05f11cd037385e9bdfa5bac4db2ac7490429e8b6e25a09239c82998f60731f618224c33cf2966072f72e13989bf5fd4b550cd1a7ea60699f427562d3c2d0a5a79918dc3fc8521f7853e0d765ea4fb55f73dee9937ec020f92d6d8a77787659dae814c854240e44811450490526c9dabc781e0f12f6d9f37bd303cd50689c6847e3679d5427542bd3f6a55a8b6b15c84987aac0bde6677ad1662b59d9cd6d4ffe9fe10023738a7b4d7d244bf07e577b0b05d9cb85200fa27495c160dd8baa3771d1ac9fd628160bda419cd9ed7a631ffb121aa6c5de816c3cc8753207f075ffef1bb317b09bf4fa51fc4d66df1d2def8ea15f97d2563719881e6f2167601fda3bde2e2a55e1b361ba0de3b169b98355b8a81ce07f2e59a4a45138e304c48c89f257666fafd60e150c1e27d61d96f5f58b9b00bafb161e8e5ce1c6990de25dfceab8df67372dfc5938dfe59d4dde3cea7d7d10b1220bbc53241c7355c335883a9de215072f8c321dee2fd81efe91aac119b7732551d1eeff8bbc8e47959f03d3707c8cc7b9fa56ef70011d79885ee1d8fa7b149f95d5b651a14bf4d2a2b6b186b78bc2ec4a2645d151a4f3f6a295661a72fd627594d669f8c0753701af8d96c7b17a3b24713395b2a09101f68f1e8b3ed23a99cc9c8e4d6ddb42f1eb9c018893e6e04b208472f7913faab04fbff3bd0b0ba8fb392ccc9d78ffdf3b0b09091b0de4de81e4ee413f4384091f10227c3105581c515ff276afc374d888d0a8b62d49edf0806ef0bddef2f648b1e0c900f5a9f9ba9e6835a78c49d422009fb34df33b45fa18e10e45cedf51e0d75cbc0816954622aac39f90102edc5732ce80d3a7fd9ee46e8b2425c3fe0d8879077108dfb740296e515fa4384fb577878c205fc5b89fc88fb833fc23fb797e6e2f7aaf4d30218b2526fad73131348beaf463cb3f8fca9ee0028619417a7e4bacded3f17c01e72fec15e55943748f5ab64bd5faa623f80f22fbd70b2ef6084b20f93ee5967c1c2d09b4a1897b8580e66e29ecdc6b989ca6962ac45dd7e3d480ba02fa811887e274c062d62f37859acfff08cd8eb3fc8211b7f2376cf622913ca4f5a1f27cbd5a7e9aba4e732d28760730ce2b1f8e27858470e6daffcd28d87972afe97bae98dc23e58b86e2eec602771a684b377c9d689a38ba1b5a3c4a37c0c4e9cb0bee5b2ad7d5802c1eecc2da72a0685ed34433d8c255d9a590ed09ebb19d5b9456362698c87df6927f9f8562647fed457dba24f035ebe20c6d2974d5f58b2f163a02c1b592e33eb834f57afe88e11432be4cd7bb08101969d20949fa51812a212a0bc3045e0d9ec41455d392390e83b6d1d84b5c88063ba3f2a5b7fa7ac6d1f2fffcd37ff5db0e8b7a036f0bc0d70fe40c8f4720c8b65bb7b2109c76d28a34013866225a5f2a28538a9cad78b4ac97ff0e9df4e8c086ae7d6718f017a2de7c16804fe7d07d0272a48c2d36a7cead56b9121cadf6ebb9281b897b41f3a094511afcb71cebbe5ab79bcf7df30f44f9e832f3a65926892464f8c7e67b9f83f45bdeef3cf7fffe5f47fb4e6e795abdd0b751a66e6e712ef5450701b7a61105a0b65a7db725e5cb5d8ecc36a81c694e3a13c30a564e792c2b276220cc0b26e8f565357acff2fc235d94b76d6c03369ec6bc65969f40d20022927595dc5a1e323e654eb3ec5ffdfd3e94e209873d0bdc1c78f8bc68939a4819231a90470141744f3e43615bd82114bd3781b768cfb5e96f9b99377ba7146b548e8fa44214888099749ebe509cd1c8794883274eab1a5b0dc9307a87accadfe9f4590b6d4ee64eb475e5e5d3467952ae13ede806f51e407093ffc3173515e779ad450f2ea8c962a6617d7192b706340ac0808b6acfda12970516193cae60bc69b4fbf0e5d7bd4405611fc2a16544300200c123973ff1fe2b7b24532f2b82e15f8ee28a3862e21b7276d931e52debca746c74dabd689a43ad8ca86818d8a01fa94b3df09add16f795a6b8d94ad0295dd53f3875abe60c521a0ac96a3a5af65056779b449479ea19e7cc6639290f35297dd8b8ead09fe7abfba14022600c3010ca7f650fd2151eb93d55337adaa5485ce89a23d7cfc52928a2e2d8f996aa68d4309715435890e9aee77945b502c26c9a9bdae051991d10a7fa7064d9d1fcb6a3f20b136869f6bdd68a8da93c1fed3b58aa3b33cc217fb055116b8421c70c8090fa8a06c9f399d20eef148969bfd383bacbc6cd0af67a600f87748c280901e5a13f5e96c068c2a487399e8365ae53595a698e1edf026220559bdc1c185b0f2f0b2c8a8b3d30346828a19c08e305152877373de8910e8568e76b282a42bbe102d253b31880b3182985386338fa2af8f65dd4878ae569ddd6632ef4c4be76388ab2ee0f793a61d61f93ac2728b3e7619a17bf6d5c795ee502ee62c8fa73647b3e6aae3c6ba7d55fe29b662c38e931bbbe3a373a4cf7155a8e65cf3c9ec0d0b6b219bac830b259688473e83b047f830c3c7edaf05c57707d834b26444df882b8b6dde284e2d52f855318b552004c63538fdc39ae3b6cccfd465d239d063c94b0705398c79bcbde42e35f3ae431339279e7106f7d4bd820ccf6d2e020654481505982258de82dd274b331da24d9dd71a9a2a110257a6998b87ab3e3070495db46ffa72f2d89fba555477d1f9b719809bf9c429dc889e2635d6a76ec7c1ffcd5f004bdd4e688e6f952bfdeca7f15a5e4594618b0ae7ff44eec37c73c6afd3d4e9696110a569d870ef69ce1538653a3ad3efe26cab3cb6228daeccc86e85d0ac6f3f83c9b3c5d7327ab6e5931f9d7425958c831c78e041c4018853fb0d3b4159ad9b995a9673bd167d3c732812053085c37c8f3eb3076e6748b1c937dc24c1b90e48e00a8db50ff9b72da7ef793abb13cf72343bd7f2f881c03abb3d1f081d3285e1046174767d70820218d9d9805a3cf1ffb4659d35d0963d862f5a7c869a50dd2f9550d7ae901954d01ed7bd7435078d8320da3b33e69c53a17bce292d2c177c062d61cfb2d742d3f2e5fe36be79faa7c3c98a3e21a10340047b5bc8d40e305cc33bcd3a802f0a62195dcb0a8ac99a08a6639ac158d625216c9a8a2ac39c218f2c4b2eacb7216536653dab912739c065b138a19c8c72dcb2c679555963a11d21a18d958fa9e91b38d148c16f6a85c8afca35aeb4772075dd0d5846c8e55d2180de1b8ce22c2bbd87e64d8b0a86407371590948c3e97a328d695ed97444cd6062ab7516e13d7f13a654b8da55107ee4353294a8d80f4ec94017b99b7112b55ba65fc5035a24fed748bb786610ca55c7a88a87ad48d0943df832699c8246f6f37f2b6c58ee5c49869051e59ab0e064022ffb2b90533b2c8bb918c106af1b67de4e342278d70668211d9944a39ab228660410dd9ab2a01701e47153e6ac939b38a3b08f0e79e9691b1b04900fd430e06086fe85603d439b20cc4b6a762080aca7a60e3ed5a4396ab2ae65e11386129510e3964d7bab69efdbe401482f3b172492a22244f67a0fc54f4bd423fe816496a50be4f791ce853f888a1b52fd47c3111fe5d7157141964551240887c0c92a8dc9a58da216ba8b46562551b211f56e21abed8705e3dc5505b4461404b2fd2da7593e5ba42993ed6d86bd353780d47230aee676bbb6d183807c433ae02ec241205a93d03fbbba4120d7ee94ad60833581b6e80b3c69b1e6c737fdc3534baa0101083decadca1d00134b036f84fa08555483c42c289a2149a468037984d0b0958fe912412097b6a1f06dd03574e981b3952260967644619d476bcdab79589c31858910c0f76605a3547ea2f64857866e52b79c8f0f5a2ff3dc017fe81e8ea0ae94d90aa8abe16a564cdbef16e3257c6e49902e678a9abac97cbb050472178e296d9d69e5bdc60119484a89aece14fdd1316870d3a7370fb3c98e33ba40a625b397c5a30e47c5e6a453f9fd0ad58cf9995e6c04a293b6d0dd52c4a9c8e53f776da9fee820a987cd8a14e0a411c87f85746d0886284be57b3e0109b89baad717be528d80ce5d87c044fe376271264732ade45642c019261bcb7dedc54baba26acf1781b4fd1168e2924ba9789ae8a0103a13cfc7b8d8fd3622d6ab304e3467ea22904ea89b76be6fa62ba130c498a56965ba6be38a40faefc64d2169183c78ab78ffe5424cfe112d16d014a59af4028984a5f43d38acc5072c10d846fd2c5504d2391bcf29c860648396004ac646ca48cba0b196738956fec39f567726de71f68ecb9c9613f945b20f443c949ddb14225a469204f8525fa15b50e00a8d956fdea2e5cbcd2879266a00a1da186792f0ba3fba4dc2c4ab263d5d21e854e8df20bcf769cdb5cb7dc4c1b5a66e374a1f53e8b1e658075cc14bbe036228e06afdac0dd5f3e8118901dc10c5c26e93822b3f7a3f96fd23dab5a2029c7ad65ae1a909f4008a9f32c6e2da19d76809ef32d709615b3ef28870ca7ee111a7ecef4758e7cb8878dc259b6ee08b28e0b869f450719fde3d80d63691e67a9f517435316259eaeaad3014c8e7de0af3a0f3d8716888f4df1f7a18555b6c68e86d98a027aa59a4d13bfa193de7a4f74043d0e3715fa21221b52258ffc4a16d9a1008c86ba34752b6d4001827fab23adc64f418105859b7ba3faad023e5522d2d96f6d3dcfe1752cd73eb3d412f11451441ff99ab4caae3a6e6563da7cfc2790e9967424ad6c45628b95ca06a9fcdac42d2d90b623ff4b10c9a6ed5718649a545d501e9833e5a7ae704835de97221fcc5180557eaa8b03871d163af7bc63f0a44201a24e8f7c5f30898b95328245eab7a92859886626fd6ce4060a11fd2cc107752c24052af2a119270a511621c896572c29c6f363aa80944d4b829046276bfe0b91e3d87c72b9b003034203bf18ca86c6473b734f18c224c8f8e97673865e338907bc35022122dc272a45d878e1897ae2baab2993d4ef2cf8db8d75a227f52e5a383590c39ef43eb1365d143aced471828a5c2853a69e996441badaee6106a4ac1b25c94486dc7e0a22f113a915b70be2d12bba840a5af5879561d01dc818e000577f5041e4c772653746912214bdfbb74169b5e6f7f4aebdba83bd454a03f4c1102139162a4943fe395e16c3034efe136a12b7e4a5fad67c012d668b8baed1a56acdb74387dcea6c52438baf9bd01abf4245294c634ee0db77d19bf7f7b81da12ad4118a174807a4bf9315a2500b874dd6e42e9595470b16f0ed3e70361090c71ebe2583b24ca923182e09a6cd50cee039490017f1d687db7ad0fdbd9bf79555cd26419c91f35ebe3c1097f4cac70f892d87a79c226ceb1f67f9ead1e813cb39c4284d8c23ff49d475388ea0a9109f03c17df8bc9d44960fcb6277220abf3167f7b24ce4d29f930289e74b340eec65b1c13d0b4983339988a214136e2e1980b7f53c2f9187a8b0fee6023309d5bd62ff898f8dfa4899fa0cc75d3fd8aab58693dcc8951a9508feb51ae26cacc56911b05aa75a46bc0a51066198b5b9faa97e244def676c1ca16e8cbef866849274635c9381ffd113807c007bc94e5c3c0b1dc01e5b6d13b87d8dd4da1c36baa2cf6f93124069ddb02bd52664229d4887b665009418aab3b115bf768d3029d9c997c8eebd1eb5a6f3ba52730c0252762d310e9e564cdfe416bd0b632fb947d93305a2cc5648734064ef60fee15d0c69ae05eae23debe5a762c3eddcfcb80a62bac5f21d560864304d0f4365168120b72b03c43fca429643dd0a20d2175ea9f050a7c6b07f8fca049c4767f53454204fdba7518d09fb6847b3c83a0a24881a529f503a46b3d30f51bfe7746b66ca67938f0e88a24dc345a24c941c24d65a2f4d9f7b200e7f2d8b78d138d9490d384849b75335e79bb087ce4a68ad4358a9c90ae681844447a7ddb62313116596e14c5c92ed0b972db658d2d646c94dfc89f573d13b42cacbc42ee4172200f20c5c9159292d221246336692b007bba8e10918b0c4032a3178a0a2652201fa4c59fffffbb410111b1f893154f6fd7f4af4f3011238b89d47157e970027761de9dd214eb21bfa2fc6f9776a0e5ae73ced9b5bebe2f1c35376ed0b4cd9eb010770ac490746daba773f38067817739a5a5e1e3c43bdb4719d56a8ad0d234bc86f6e14aad90848c1293a165cbb759d2ea759b970204bef01382f31194dc0fa994d52f90c20615f7279beee5cd8eb0d5100bf6928159f8309d84e4c308638728a307abd7fdff452b69874356b1b5cdf3ef321b0dac9e56398c3b88b0f851394ed955e70d4746ed618810639bf5b5f8b93d98d5e7e7dcf3929f2ac9addb64f5747f06b78e13cf6212b646a496cd0b21600f0582fc1d2924ec2274f7d884aa6704f8ab4af0c3380e5a80f6f1673d75d87eb1f57830d2f220fd7e77907ae3c915480a45e83e7c86ee7aeabb3f72570ee16743a1c15d3a9d3603d52a371196db74bac944ee0e2b4efc7c17cafec460044548f793495f4496df63db817b52f82b46769359e156173720ed1db9ed4289d53e3e75455bd33ae8a1185e9b6131b0a38a295562adb183946a7c11c46095d71a9f14af1adb00090ad5f450ac61c272a208822590735f55eac7dd085b6706a20d1291a8f5c3cbc0a77c1248abb47c38372f70d84a3f4394d7af41561f9741bc8f02a0ae054f1bd1d5e9a3cf970dfa4525b591c0758e6422b563d753e3f565e2c419ae202f95870924c9cb1f9a3bd9d118f94e4081cf349adfb481f9197b6e25d5be8f1497e432a95b15ad401a2b7723f933eff9c1a2bedc2e255668adcc376054e01003c1544241445b0f5f12f9c304c5768f13544e9b0cd02fa36502bb2125bf7bf691afabf0969768d830899737acd5a9f465d7cfbf7fbca2ec54fe7b662bb62b28c3d4c05e36a7206b25cd9d264820b0406ff50c98df296de50fadc99c73eeb7632958d9f3d10fa9d72e0fed8f1f0ec6704e4f1f1c70f6b27a7073c7f2cd9b603070602177c8e31b52444f27a6d84d7a3ff4a32807e62bd7c59f7d8552834da092b61edfd84b8d1386e196265e18bae047d135b0308d791b789c0a26a1b842ead43ab816867e387cfe29e4d4a8d30a8ffa3e8f7d641985d919e4627204a16ac5d4346be8f7e879f4147d16bd3d7a9d12025cbe50506151d10541b5f56b9f05a7a3f9d1a1e70974e11a76bd42f1966ebc2153e4f1a02b5be52cbfbda5648ebf7b04c697e371af78ad59e7a0a294800489b14a7cdf049de29fc35ffbaab3b2ac924f5644a1f719a0a9713bd825aedf74ccbbd14158d88e9f7a9b5516983af3ef284aea870680fd9dbede4f6edf039be872c03a1cfab52bcbacd47a503a2329286910cc5ec8d5b581185a593ccb671fb0388d5ebb946679fe0eed6edb2c995ca65aced2d1eb0d3fed8112ae85ffab8de4b2515148f787e2e8f6d910886a2a52495e63f4e1e90980407ccdf24c5a3d112a0bbbdf1342d0fa18fbe8d509e70ff05afdfb66a207c62e2af25b83fa047a15dee2ce0cf18cf7f2d8092248c1c8aa9ab929bf3f8526490f3e4f71eb74f538997d762ac8b274dab070b49ef3966dacc7a290a6dc37f47d95c0f6c564c700c23ec488dff7b019f501b64a2d570c712b44c08dce563ccada06aabe82b4f2ac2d7b58073ad4ce9dbe53887b816f4daee529e6f49abbbcc4ca3390548c1b1bd2fa350116353bd0cc7708777f05cf120d12f13c59e26e5ca5a53c7a42ad57760d3798435de0d56d6cdcf887c2abc27963c382aceaf4cdf0a9fa25b9bf5b1b8dc2435f82f9bf0ad18a0628678436d870e433e1d613bf7d9c166b00ece7eadbb499c7b6b474b2ed669d67ae8e4329d9e5d93f40f473e3426d327405d9f7ae3d08a52911cfca5211718cd95608200be20c031d1f0714a6e0dd4c079990a89221acc37fb27f798d896eef713e488f0e34c74003b2122dd0fd60e3d6897e82cb23c9a80b4581e6b4e22861af6cfdf097e113fba925ebd245355b0da01821e01765ab3beb0728bfb7a407139f3c06195abe51dcbaa3abf6fc7e8b353f835fdcdf9ff59e34a2f2a90efbab3303bed142d9177ce27a754ac73038ca87fb37d44272dfae357ca2b19a40a06ece0fc755c249291eb014ec1194ce6a8141ab06e1012f6a2ee0cce359987de844eebdaaa287c983eb8fcbf0a850971c9f35bd5141decdda3d8ab50de206ed2f94a5187a82d15052b820093e89a9e0fc4d43af6b54c474f737665c58a1b51ea737b43a4647eec6ed6ea5a5fd4cbf9a899372dba6cdf6d5dd5ee0c0959b04ef391228a5ba4c60e24c4c27e68935d19b282727bc75b72bc950c78a3c9a1922e9462741a31b64d7abd197d1038b2da61b7cab219803c4e949cced76bed93778bd82d6e89fa84c6c02ec16f24c87f0eb084c3aa570f7328ea20587be1aed1af75d2099eee8431bb7e126f81902c71e1df8a2652e6499ed9e919a7ac4d9397d1cff8aab2ec2d646d889b9f141c3f5be8cb401858b41afbd36b3585b3948114b1da5bd86f7706ce3f21aea46025bcc7d082dc2f48d0f9a6a54ccae3f454c60bb52300b433428c8f07e8e572ac2ba5806d3f0158d08461b19100455976f2c7898e89f03f6f77468e1f54ae87e1d329987f6beb462b323d6b78bbe61813264820e5c33bf66420abb842f04f4e7811258d125596a2a24a24abb0d34f52413738aa66d7b855b88df426fd2a3d927705cc9ade99402216735ed7738e89169b8b80a82d084391841c8b148a3c38dbe02f10d770d289ffa163d59d7aefa0d7b00afb9241b74faf25d6bd2ac3d287fdf73ec2d0f4b1d55de9b29070b4accd00ba9c544be645c464eb73da3a8556d8bcc22b753fafb75984b2defdb72f599cf7b7ac21231f4071a09137fb97308ababc57ad102ed469f114ec4e51af67042dc7e2fc5ba719d392eba54f43ea93820d31a6b3a2c7e38f5ca5bba7910ccfd6a1c7f74ca313bcb471c2bba6cb11736ad00a39f3a7397c406442c146fbb160097ba9d01b4787cd18ddbc2528d5dcff7260dcdd4b62753dc2c39e0310481092c915e3de3fd6b75cb55e2be81dad9c0b8b93b4912faf977738dc8abd50ee656dbfcca2a8075e6f1e4b8be36dc290f5abba8faaeb11f65c7de3a4975a23a427144ce8b38d40c484497de7babce2ffc45917a7befa5731ef88ab5a93d552a1b31bbfac420d1425acd248057e571f125207062d700011aee7eb185e8c7363ea10be8dca51f7430640871a903cad6505d30421f1209cf9c0d7be7a194af60f1180a46ed4c0494ff7c6e0668164c5d05c63f9b8b0c62f50fae921c448fa8800daa41a089b3894c73079e8e7d8e4ac906b830e68e928e35d62ee4fc666af6f4d51074a6334957d4c9edc89675f4828d35323e2592b92c00793536a32c5c70350f77c211e14399036c75877fce5b67599043932e7bb06d248e2d0176114300c99085d17e5bb57dc4ed15f936765978fd2223c28e928e3b622e6ac143c9e866012fb78daf45ce0f7aab6932c2cec99872e47d1ac49c3fff5bad42404540e9d1d3709260b5ffa715b000d451b684420fc7216c53e4e464fd708b391d8407655a593e9069893ed28a0a24a6f7647133d76272fea9988a0e14677cd99d26a0086423dad83cfd133f153f87093f84e204f50bccbf25c9f48a5d075b866330269aa53e183c257ca892125b5ca4a04dcd4701339e800cde6e7b670bdb75a5fc98f57f5c5fd55d22ab44a2c39ea858e0961c94d642875e690b30783614d7d01d21c35c2dd856cb8f488b3e5d6ea8ece16d68973fd3b521bd861ab108bb05a33f818865d6fd7e3f5dad0f2a587a42aeda3fa168210eb0577a9e05d6b487ec4df51c7252b5a44e47e03a985774041eccae815c0b9d9ee9c80ca49d3fa4428f0a94c99616eaa5302dd055201930c71fc407320a3fd5d40a34386706a0223e3b2b95c0b9484b73ef7ff20b240e3307ccb0a08f96225762a3ab875739f887f686ca96e3042409d64147c72042893e178bf4be065aa450acc6d3c4858ef5bf8effd00eaae10e24be9eafb13a7cbf9c97a709b3e514f98fc37500bc5f93810a3a7f081c85856b68b4e617e555663dd3b3e499108af3760932fa5cb682a492c8cca2f6eb75b75f3ff5243137eca5ce986d484a5c810207d55727362c82729dafe04beb48787f348536b392f7c56c95fdf75b070a8ef22630c54fb72556212c415bbbeb324abdb72974cd4b3d3a082485403b85dc25dd16913d740488725fbcec424a05d1b5380eab89e324605830abee34dc149238a3698df7ef444abd9c45e299dcb0a093ef0a1a7bf93fd88df61ed02c5d53001a6c469a7a1d93fd1675675d972a7e5decd0b61a51d2ea2889439afdebd957c07968a82a78525a44c925de87ae7bd35ab1f7acf13807a86097a9f261340a65bfb4959cc0a4142581100ff9835e27c369a987d98ff0eee2885b559368f8409d0df5bbbca961783a4a1015c09df370617099e057091993f1b492b2a45f4974a178274d7138dd61ccfdedc82d628aea34422367b9cad2e9ca28daa804f588ff8b1f5da5f716a520e34d5be396bf4b37f0e18424e254ee473d8b2fec67da80424749c79bfb731ab194e532d30dc499d8623cfbed3b4ccb9eb5a5ad24a6d5e67b6bcece7ccfa53c0fbe02cb4172446c5300dfb5c9993c20742f3e52f783620eead3897157e8fb0a7609d03315d87c63c40f6f7b5c8bc1b69a6981d2e7899040d37ebbb30de168c8893e460403bf6f42dcdb36ca9cbc88dac27b15e87c20910722f8ca605bc3a56f4ad89ad3f975f308dc4119d31439fd7e1ec6e489d42c33b04cc17407fad36955ed9895320aba4ab25fbb1232d3a2fbbdb3753a2bab1ddd808c9e7a62c82aeac9034525b6d6a3ba10cec3953365eed0a2e4cbc9c3f5973156adbb98a0d0e71bb1234178684a2fa34edd44b6e7d5c4404641ae61fb33aa57c5cc6877718223de3861b97f719a19a0af38a1a54500ce7315ecfedb4c3d9b5e528d08510eb74429ad97f64e0d234db31809e181b77b9a49dbe07dcdbcd68010c925951a656c433dbcc83c63608f3473ea79b8c826c2fc6f111e63ddfc62c5d3cbbc773edc9ad0170bb06090320b0724f81bd2d6808502e6d0f062836bd9c899834087b191e0ecbbbc3d105402ba25fe7c84de35f128e2718329d83cc96a501771b686bace98e429cf94b8ba05ec042ecb8c4a5dc92a59f1943aeb0970e347f1b1461a2e022c7c05ce2544ca0d531050aba83ac4af6059c62b7e87af41a3f27388d37fce2429c7ba295768c117d74b7853b5b06fa9d69574d5882112d994790b2b8b989d01474d08f1603d8a5ab2dd255beeabc3701e17b8ae8fba9083f674b429cd0d700d900e3bfb96d09d1edd93f2a952850e1d284fc623bc7184111ce187230019a1902c4925e16c7a325e7bc8556f9aeaabae43bf73ce9542f3aac246b8821a2103da0832f8b5ed562d09efd8adde3f6d8a108251119828c28cbb2bc04744a0830855e8159a225ffd137acb4d63af0d44841c22c4309aa30b51041ab35e4f34a39fa6faaac635a54de35a3eea73ad486bf59a83fe3cb34e2f2906d5b9bca67df4b18af14d6356f3cf9d77587fb583fd12d5a57a4df5855eec679875e713bd7bab37c75e76675d6698d5cb0e42b3cfaa7bae7a4b4c0871170db9fb10775173e4d8e24a537254b9e400924304820ff28da541954e445107a93457bd2520e8f80feef881173f187f60ddaf71d4192d7aaffd52d539597c2086bbfb40e5ee3ff8c8070718c57187fb355e41e34fc97bd5288f8d136befd5031cdcfdaab764b3a2f8f1c75172bfea4de37051817a30470fb0f01e0cf985777ae0e27efd4ea13a67f4a2e6e0010f8e70771e3871d7e88807a05f3f25f3e0c70eaedd36f6b4452c4ad5a6fae90e9a70bf2ed6364c4c334032a68f0e76a0030e5cd779927450430e5c9083217290030edac081d008071e0efc22c1bc3a64f5a7559b68b63af6bae1067b5e54a3d45f6382507d5af49656ef34bd2b5593d28bb29b5c4936d516bde6f97bcdeaa8b5929f1b58b941941bbcb8abdaaaf499aa2338a0c031c3027c640330463668327ae38e37ac78e3884b9b373ba62ea2eaf26b2cb964bcb4ead13758a8c11935b0400d8250efcd8ec5302c8b2153db92dce8c20d12b89172f7f7911b2e6e380dc0a0818a06a419e031832c334081bb5f7ac40187cbaecebbff738a6c1c70b0a38db98a98461b7315b9d9c9a38db9682c0e385c78c75ef596eeafab1af54bebbd5957a8ce5b972935df741c612ebdad26d1bcd821284a9b373bd65e1bffcdaa51ad7b1e6b9bf4aa7e568da20e010da0dcb589ee5c75c40206c4e00631d8c26a73c83d0635f8dbc8d2c6956ba3346d60e16db4c1c3755adbf8e13060c37d55b535c1a074c14088aa976c41b22183fb35aece3c8ae29aadaacded2eca798117ee6e53d4af57fdd2a57e7a91a86baffb8aa6b8e420092dd0817b0bc268c106acbdd60bc65e6ab6fbf5cd556f49f7bc3e7f7c862e0f0874700077d38c8cfa97bc6bdcb1d7b8e25e5a2315ca7b8d1f6ac0a186aa86f52bdf9dd3b8e2695071f72b0d05a4e1728de39f560bb4022cbe823406e6dfb47a5d818b5f308fdef3bceb355fd63c8ed030e3da6820e1d78a7cac797c4cffa609a3d7647af49eff3940ffa6c9645aaf0967d33e030733b0986105a3d76a9688b8b3191730a3e47e1531c396ca90c3cbd0650c800c179031c56537ba5a8dbe58f5d77b5a6becf5e83d77109a5572a3998cd3ad6804191f196e1fbd162608cd2d4cc620c2c6bd251cc3660c1f760b592bb6d888d101b762f942765bbb73e16c7bb06210410574a820082a60c38a47703e228abc5001055450840a808e908e60548baa7099220315b4a4c08e23e2a7400529a862ffcd75087a4bab8a7e8ce014f47077abd74bcacc118bb34649e779a1ac563f3f7a93ac6a3ee70484eeec15fd9ff57f5875cf56350f4ad5404018700a80c1a12935c58f52f75581c100304eb74ab67aed5514bf28c2176eb85b6bd5efc1e48bd3fe7f216345f5bf008287bb157b38e1c5175e64e10507a6e46d2ffbe875ef917a71f2a2e4de8dbcd0ba90c31eb136c6da15fd749797f4114520d307ef7451f2abc7762143132e5ec00515bfb84872a6b810a1c08afb85d1ab55ab5df74d527eba51f0040a4a7e5f45c1aa3c0118eb3d0199cef3da9ce7b541b2c5145b64608b0a6cb1dacb8af6baf0bb8b707ab86ce1b2b328d322065a70409b371511400bcc0726c0c3dddda370c5dd936082950992b85bf1ba8b5a4c20c48aee8e258b2b6e5d8c2c1e9005b6ab0eb2246b2f94b5a2bb5731e58a2cb02c84b8c794a00725b08168f746b5cd2e01c94532eea21e462440820427094615a5a25024e0e1a1b88b2a30023b4690650458dc8aaf5a1bac5eadbb088c1120614551fdd4a47a746666c79280646486748d4904a8080680c50ab0b8020b203caab8d09c57f4def5aecef2aae9a5d26894f57726d56b57e8c57a45efad09010e0190d1155f5c615e4143ca34772e8cead55eaa2ecb6b66f59958a10377bf1e955acfab63c504ac185a91a3b502ac028e1f7b55f184bb5f18cdaa2a469a2a84b85f54cc715141c5e253db9da97032a282e47e81800d100cb9fbb561d48bd1bb6e559b4010e22310c8981af7e00352b03fe93f120d74ed7d2a5328bb57678aca3be67f753ed66a907a9df7246ff679bc2d2045901425775f89400aeb812cee6ec3ea3c53e6feb24c35e10111b8af3d5cd9923ea5c28c1bd5e73d8d41f734edebd5a252581457e5554b8d7a6cf1ba8bd835db7dded3b597faa8eabc76dd4fa6575df7aa35b9ae486bc7a1cb73b2e3b8ae59556d77bfa38af5c7dd9ba001ecd7767717a4a210c5a8011f6ed3539bf6f7e9b364c9aa57ad954411ba5f5664525301c7e89bf6bf697d3210ba73daf784f1cea337c9a3f7545d253aa2b8c228ade664a08a5ff8d79f0c04597106d5793599d27dde57228aa4faf8fecc8c921b1d1999f299904a6e74ee7a6fb0aa4dd39e99c13b32294ad591299f09aaa764559ff6cccc636da37a74fd9f19176066602ce945a67c2641688e525e127f7ad5f207df3fe11d9bbb5eac7e2aa4539c4df7aabf57f451333a3237aa5ed319d36acd333a326bbace60e44e228aa2a80989a20dfe28e5adf9cff9374d332e902c49466b25a772bde7796deefa3cfbaef70675d39f6dbe92bdd3ab02edc7bac7f4c1682a67efabded2de36e9e5d9a77d755294aab3694efbeaa4727e4afe4177f6a337c9927daa9f520010beaf935ed5cfaae6f1aa66ef8c42a1b9c9de9f87f67e35082745a93a4c0cd935a599007277263626883001440e771f2d018325c2b0a23ea92c69ab97fa6b7af135adcad1124796782165137a4bbfc2812312e0813bfe6caeb946fdad6613672401179817f4cf233229bbef9ac9085c71778f4095213e1170e27e6dad028ac08f95ca95eb7f5b23232a5238698542a56e56d5cfc68f310d151d779a1115d2c6f842200b084881808c5e571fe501317840081e30e47eade85d877ec4788755a33b94d2abfa1931bee368d1f4aa7e1e00bafbe5803a1c80e51dd0840352778c69d6dffaa41aad038a38c0ef480930464a7440099d6b5c7fbf1251041a579727e6d51435dabdadcdb549e533c1693e69409464266c00150d78a201420db017942716efbc7fa5d112b827218124408779b1f891b8c3dd1d09332e245223480049537bcdd9d21ce1c511abfb052394f7fed5cb6a6f109a492b12e645a32c0dc64cf01b91c5c76dea5b1a81c5b53ad5fb40469c2c90113aee41465837a208386c28c24a114345407177d4ce3ca77d4f3333333b320cf041440d8800011199888d08158658c110510c0165086c8a12a67431a501539c4cb159d5315acd607501af317d6494f8ac4825383a403b38e267ab8f62daa2b8f3a8d92333da2661d294aa6146cdcad817bb2fbdda150b435118ba628888211e6a6e2c91d106a1792c952c11eb330a1141a88a10142125a93c52704c913aa5805244d637dcfdf2d18ac5aa64b4eaacbe4bb0a1d80dd8312a13d42a46aa128f6aab7a149ffacfc799c93396f60853b2f6d7acbef88c963496548fdab127069fda8e3c3d96882df1045df4a24a74b5d70f3a53e6abb71c47bb42692e28e313fba7d59e41171d6346fb27208bc395f7d0e5196fd425267ce62f336abfc6a2693e0d91720429389082454a14529448c156f091941d5237dcf421d91df60e7be8a24aa5179f6b87eb3235295b12e9bc5bdf8cf40a34131a094d049d032d039d00ca043d002a4275810a02f51385d159c5996474f638419424a2602321723012828aef2d0666cc4ae38b1d4f54e3157ab5d28bcf686d8de9f362f766632ccc08938d9664c517cdc668a50fbaa8fc6a6ac7acf466cc8b1d6b46ad6489d8ac6489581e4bc4d6a8a991b3478e5898175134b569c4f75551fca07bb3904d9a1a2d910b13c16fde5da636aa37aac96bee5c5b9f7685da7d4faa265d2b040bf906d904eeae828fb2084639282f609481c82b8c4e5d9c28303a2d0942f3aa998c30230ccfb8c79a1b1b031313f35897319b67e4c10187ebdfbcf683d47b2ac9d48fbd56e85fd57557175d5d4c736df25a53eff4fcd35f302b215ed46b5abdedd6765fa77d4f661da695972d64edaa7b787ed54c56a77a71b406da2bf4f288c2232a778cfeeaeed545517a45efa964e279a1d17fe0f78f7ec1bc589817abfa9ec7dcfd855c1b6719612cee3ec2559e1c82e2348fb0ce8cea51fcc2be469546c731b344c634e6bc8fed79e628e5ddf99b6cfbfb149475b406c28ff1e9d3027787e22e3641ee3ea3b393e6d346fdba73d59b923bb87b929b99fcec5f35139ffd6a5e5f09c6341ae8cf34ab40416846536a69df12fa49ce93667fc63bafeecffbeaac3b27f9559b42a5559f3fdb46db966820bcf1ffcd5e3d1295ee8952eab3e6cdfbf3b3d3251be751592d993e1f845e25fafc5987bee7b4e626184d6925ebd0f7ec34a5d51eccbbd1257bf53feae733fd7fac79f6abda6667fd6daa4c54bd7a2434a54d0d465339ebd0f7e4acfb6b7469a376f6e753bd38ebce49f66f7d96d67d936813dda1d9bff355a2fa1e9dbd8377f67ef4d79b64ff59a24b6ed6a1efd9a5fd59c95e3d127cda57e7b4af0e8f2802a934faa4ca132a4f3020e4d002082980f00182003fa831fa417d8b6651cc2f166684c9c871fd1fd467b4a67eb1e3ce388e2bd292f764f73da52986c10f3aee3b25e5f78ccc0b9c48c1fdda3aa734e9aa291aabea1c7be58dfeb6d77e1455ab543bb5d1ffad7fb0d7dea9f4da1d76b8aaaf49c0fa41380da6de31ebeaccfae2d80bc33a7bc4629dddc1e6d1b433d62baa332adf93c65e51b0ccae572caf6957f4a219a531866596b43ac93bf45bb4572ec5d871bfaaafed845b1a28790236a94457bb05176c307ac52d8aa2ab011f3e5a6f31dd5b0410c505a290e2eef68649c9ce9cf65dd32884789538aa8860846249a3a5a9c2837b1521ce4497a0c8e2ee171457ae0d0515f70b0a1d285edc3390c5531998e2a5260363067eb8bbaf39dd8f2d0cc471a618b022c42d0c54f1c100486abb22f79fa98501b72ec0067a01135817d071bfec0874811b0bbc61010b1c71b526bd4a6381520caad1176b811f3057b93ee9922f1530a302674acdb80258057e5c2bfa14d8c2dd5da5c0e8d7b5a8a6a1408cfba543b2d79ab35e7f4afed9270dba44f5f94197fcab3957bd256cb3ea9ed3be4168de4168de9907dfd751b58d921bf4984210132998401ceed604c6b02690c504a4b81547bbb78a6693e9556df3aa2ed76bea1185eb3d9620a4c98be625a058028fda5ca245026848c0084b023c98ebb511b0c31d4a10f64910f68a000b223081114a10a77d4f4f82182f542b59533ef851192802985f54b250b1e254a850e181ca5b089c914ad7dfbfd7bc73137ba13f25dbd33a243f9a57f44e5991a3eacd15cda7f27ecc0ba179ef157d14eaa63ff871fef9198214d94846b1d76eadde349f2f94559d4410ee563485d22484b80debce494a74b5ed9f809070c3dd4f248dbd4854f13465d38db58d85848ebb89040dee7e3ac20e9e234ae06e4ffb88268e00dd2f23e630c28abbab2923a8b836a2848df861ea1c26a522cc28828afb5d7711a5225c7c33008e7d4f0cb042f5a8ea51d4ba19f0b2bae7be44c4e14e04134410a1c31073a8a8d63b0f6972a54a434c31c4912973ac59d542a4b6d0e7d36a6e8c5e12b6a670614d29a7c060add258d1c738b51feb92b43e89d99d4d33af0430b4022186462a3254a6cab2847020a48425f4e6a9baaad5ab1dcd7547b97feef583565b4531f2b12ed1d549632f4ce3dee2030e04b18430f79d3a82eb7c8d4fa08c4f2c09caf8649fd6bc5e685e5dd5dd51efcef6ba18bd3ba5e6fb2a0bf3725168a6b11779d537b556537bb390dd240e904f8ffe1469ef21ea8e523ebe313ac85e3b8ef6c88cbdd9c98fed855fddeaa716bffa42e7b52415c63a4dcb7c5275b6fbaaf9558d5aa1b7b4a64a9c49a70b651c9f087d56499b187cff74b363d1f3bc796566ac5150c6fd04e771b47aa5b1d73d4f1a7bdef5e7676334a56b4c9f35e5f3ab6672f3330551005264f8cc4eddd2946b4c3be8aed7847fa7aecd7a4deb35a53d32fb514a64ca6772d55b32d170bff29a3af39a3231ff1d456b206fa963fd9625f89881f540ee3eaae03b54b0380c5c02f714a59e52947ac2e91093280ec198dbd20e5fa324c27d8482b389b4229f8cd76a556f2a94df2a712859701fa158d293f122abf845a6eefe16c983b5ee1c6e5d2beef709bf7606ba98bb5fab75fdc2462c5a55d99dad354ee1d658f26b5ba310bf2c131c97651a7214b52bf2fcd232dd05c4b1002caef392fa0cb2167072173a7fa3feb48019dcafbd83b3090a90054588bb5f41b0c00ae2034124b137a3a92775584fa4b09e3c79e202440a80d0028820dc2fbd51aa2e5f881d6347d3fa830e7ed080f543ea5b9fa51325584ec870c200cb09d0d63b5bd2b59db0d0e4045693299aec34e9c1a40417cc0874adfb7febf57e89961613cb5a9287b5848c25424b3095ddd7aab51235a5579b44a942f7a4aed6fe69557f4de919997d4f4dac88eaacdae8bd76e7cb63af0bcd41e8c5389654c2b946989225edbc8c76dc19d5182b6e0b43bed80bcd16e6bed8ebaf9dad57fb456e9acbbcbeec2c8adbdc79bdb834da187b016d7de65769ec38c238b124d3cba872328e30264b72f232da7d4fe356e993ddbbcc42685e337a53d4ba816c7e4afe511f88d5554d4197a09ffaecfde89a9b04a15ab536b08216038ce3782ad1bb7e909128ff69d0468da671e764a2d68e11779d104ca1b344e7003a02b07ac0d243067a30ad1e8cb85f3e561caf9d1a6dcc656a711c6d8cb8afd545018d17ccab2a7d8ea345f399d73d7451e30873d59bbe3c4affc4d8cba23ab56ef583d60ffa29f9679fd6f55a8df7adb8a2e88ebd52fad4a516ba7baf57eb734afe75a5de7ce6a1bd96e3fe53796decb52f9f9c9d1c8be62be8c2b117aab7fa423e00d80000dc61785e74707a63ae47556d4fe2481a6160785e742ca9c692845e4d5f462ba2a2a0f9b4a7f2e2d8cb46013c1be3eb0e46ba5aa9b89ff7e49e352151d4844431a73766756ba60a55d5a587c09a09c235a122678acaa69cde196c1fb9c3af0f52efba75c9bda574640a47f35dd7df47927879c4064be60e77fb44e68a63a88c12ee0ab0643c991c2c991f6e49563c62a1988c60f16d040b4b631971e2da3272449ce312ba96888528c5afd00916c5b9ec7e75ef946886e0f0d028c9b9595daf6a68afe86fd567c9fec01430ee2a58ee638a8f958f15ba3ba4e8c2fab0fb87f3093932632daf0e4f0c2b635f6cb0e2baef897a54acb8a1b8bb0fb7bc289607648fd860f1252d140f07f7bd66d274c4066bc2620f4b6a3a33dca394faac8941f5ef18fcbf637af060ca8444b188287223e7e26e77dcdac470f72034e3fff2d4e847d12a6977563d6a6d42ee56dc84b8bb0d351a1c9656056ba3a36eba3521ba4483726645fd8c8a95617ea5528b6141b58dbd70b0210b13e27ea13aabbf66b5b476e4c951c264d4d82a72a5c8c9ad2225ebbae3fa54a75f96a6b6327451d7905f0870ebd271f76be8a262b2acc81a58103385fbb555684c694d9148594876dd3afdc12d928ebb45e40e7b2d2253e474e8edbad14f357a89f0707790c3d4dbda61053ba4bf975cd6a6d475071e60e28039227d181edcaf9719582f63bc9c2ed5a3f9a64a8dedcff5025a6bbda4ec9029f49aad21239aa730f129d9a18b1af2e2ee970e58bcb4d6d2a18a0e3a79eb606d0c02b670bfd654ba664bb21030b42f0274dc5a9b43969f1c52702a4dbd966f9aebb5aa7abf7a1fa5febafefe3de251dcda7af53e69ec4596fbeefca77b774abcc101a2b1c15152c2b9b1302bf45a33bf58d5f7bcb10128fe53f29ed1b6d4959536ebd63ad7e7d5350e3d3e725da345b5fa63afbc3f9feafd91b492298d2d9a873caa6356648c69ea215a5df37a85f24e8986862734b06015200cbff093fb3c2f991fcd41e8ef5cfbf5bd564d95a5de41f8c7f2998cf66ed4af99c65ee7db07b2d7b5d79fe4cdea15da3ba7f60ccccb68b7896214b57ed0785af5fa7bdc3f25a3f29aaa3968cea4cff9944feba93539da8b5ed4ffd87dfde75c4259cd288dae4e7ded34e73345dd578d292a45ea1f7ba579d5fb7c95350243c41ab13b5822f6df3c62d3bc9ad63f8dc0a4797d29cf5b9a8ed8d5fa67912296b4ee943a8ea3bd484b8249f3fa626356a77acf8cca3b6645b56a8ea3bd76ddb1f74c05a579ddd7a2f9aea4fe374de3b85ab3aad5acf50d695ed52c7483fd319fe99acf148ac67a4b124242dcfdba568fc48a98102de1fe827d52832e49de54a722d1ddb15b414277146abbb09818324a19b451eb16c5f2854411afdb946eabb484ace69f232cee7e997af484463d8ac61a95dcaf35faf1579f2e575caab87b8e8b13cbe587bbbbbd54fd2f6e01e00d774ba381f49a310ece353af83c69f097548f3100b06b7d2b869dad18b670f71c254c7a6248356ac5f043d5257be16bc160657bd282a18afb85c2c0c3de802c20598060e1eea325ad576501a1620141b3f5c21d6fbdb0451277d7dc7a2175bfac1774fc72218bab17bda4f55734960b66b8bbe5421520cb051ed65f653bc472e10790d5c21c6eb59002f70bf5a8991664ac1f70b8fb905b3f468cfe79b755ad1f77006eb1a086c5026ab120833b4907e59ba26e6983d06cad7063adf0c35a4164a970850a4f2c1548ee0e835b2ad460f960c3f26185bbcfb8e523c8ea81071bee776b34e6daeb4677ae710fc168ca54b5353262f44723af9a26fba7159b3ac6488cf83ba07987157d946a49dadd31b77aa8560febee3a6eb5582d538ce34e59bddad525dd5c559f17895b2d46ac1677d719f5286d514bd445c6389688b44438ee7efd8ca3d56b145d5a3d924fd1cc738d63beabfae57d12e6068ca6ccb2c82abd81dce105a5b1782765aa1fa5bc2a909a57f433a9ea35a3369a3acf1a1407dd516f0ece795ed48fd640e9b5515fc887c607e79a55f7e89e1b0db4c2574d69d4f3982a13dd2344a808f7dff9aa336a7a4b6daa25f585be47e724de22047e299925628518ad91315b192bc4e82d78fc29959258199b473c6a88c2134651e040ceaaf5270a4fa2100028a4e13e4221a52915df9414fbdb5e50b0001440f7118a255de94d2fea0945784215b7d71392f893d15ee74963699ee0c21d70b8fb08c59248faa47a325eaa4cdee100b7a427a3bd70aec1bfde72eb13ffe88e17bfeef8e1ee842bbe3a010b77271ce1a8134a4eb8c133d0d0e326c030c1064c80001370eca8c38e1bd8f180911d42d831431d6bd491d661d621835f2a8b33f9a775b431774d9d7a93f74fab3ef7385a53a35aafa38d813157648ad2259a49373b31646a93a93dda980bbfba71aeb117ccd0ab37bd27cef7a2ee4ee947ef7aa65079eb337dfc92c9256460093c4a788212e4b8f08fe3689fcc4350d446092250c2121e83668baefafc51bfb45734a56d3e08bd4a567dfe6c6b6a8bc3113b16b1e3682fbd5eadaeaf4ec93f161b92da8d6538933031646abfa8d4c73893a825dd806fd8299d0aca2baacf34b566d2ba5342033eb2e2e3232b281f5979808fac80c04756bef0919518f8c80a117c14c60a3e8a4202417eb8301a992f3e328df8c8ecf191b90073c847a6037c643ae123d3033e32b568c1058c1cdc058c22ee0286e82e60e4b80b183eee0206102e6008e1ee30c4f02388358aa9e2a3182b7c14d3858f6258e0a3981a8041fa28260e1fc5d4e1a3eb878f2e02f8e822e2a34bc64717921854b0729ab84bcec95d7284dc250709979c2aee926385bbe470e12e3956dc25078bbbe4fcc05d728ae02e394c20c012b6706b092d70ab0eafc306b796e0e3d61284dc5ac213df0c432c015a50f9280a09f8c8347d14c5133e8ac2033e8ac28a8fa250c34751b4e1a32876e0a328b2b8fb00acd1951f3eba62838fae883eba92c447579e5c91000066186179228e353c480b101fc5e1868fae403102800b107f4106008ca460858fa400868fa470c5475270c3475290c3475268828ff250c147798c7c94870d394bf8280f928ff2a8f1511e3c3eca03080fd2a2011fe581fa280f237c9447133ecae30a1fe571868ff2c0810b7450f1111d557c4447153ea2c3043ea2a30c1fd181c54774f8c0dd5d80c10508901116273ec242fa084b141f6111f2d115066039c2475724e0232c4fb8cb86c247583830c282858fb08451830d0538000d35e88083d7e083126ef9f0845b3e68e1960f2d70cb8722b885a405b790e4e016121edc42b200b79018e116920db885040cb790bce1169225b89544885b493cb792fce05692d5ad241608801018603895dc3a8d6e9d84dc3a5171eb34855ba733dc3ac1e1a32ba88fae30c0ad1312dc3ae1e1232c61b85b1e046c710b1ce21618ba052a710bfc15f060c25df0c080bbe0b101191c88cb88b4e223d20c1f916ef8888cc347e4117c443ec147650b2ffc40020fee82841d77410290bb20e1077741c2757720410840c51577a1c20d77a10208ee424513dca58a20ee52458cbbbfd042901986f0d10c0ff0d10c1df0d10c57f868062b3e9ae105256fe30ab1da38311f4fac18eaaa20828f9f00b8f8e042c995161a34b9e2e30932c0c2dd5948420e7ea032843174464b024065e84701e808cd31f201157e854a883800800422567a6411c38bbb038004180901d84089510c827eb0b07fe081871318b1c10756b078a347c7dd5b3c222c19810002e82e9281087cb01e840d40203e274e6c700508104ab6b031ef68210729c01bfce0e472c54a961f5344db42122b70b8a00e273904008b154c521f400ee0a1e50256f80b4640c35560820f6894b0e396124e6e294104aea4061d5c0061128e702b0950b8950422b8952507b7b2d8b89505e556160bb89505056e6569815b59b2b8a50418776ff9e12bf8f01635dc5be8303916fd0211b5af4ac6dd6d081243e8ee443c480c31140902431a22fe5507ad4469101874d6bb4de7ddeab5ef70b781bb03e14180b0e123023ea80cc0dd87113e8a080284872986b8bb959601b8680a09d8ea257445261f75a81e552164001a04897444c60e6198219c5f56f393884a549fd5fc24d65a8b0631841dc2d9f441f84d3608c1152a40713a3263fea942d011192216fdd364c2a7ee21c50a5fac1bdb23476ca96276a606771f6504f981fdb1466d901f98bb1545258ec86ccc117b7d10fe96edee4f3c080b2bd6e80f403b3634251a1b2b63877056409015e4d8ea5524bda822ffea4a16d9a8eed1e3877b8f161f615ed2abaad094288e367b46cb8430218d49268a98104e1e3c38c62463822ec13f0343d2b6d48b4c0f91a6ea54abe892f4aa40afbe8e7b0f5f634fe1c6bd258f33379182e9739e34f8cc4ddc5bf0d8ee2d514053a67b0b14f0cefa2d4f80e26520e7de7207e7047075d5267899b6adaeaad290faacd96846822a9dfc8a2e51e9d35c822e39cf54cedf1af7961fecff9c2034f7fc49de55f7e053eba443383332e533419543e799eac99c684e36279c93ce89e7e473023ad99be63c69d69286097f9239084de5a0bae7d7574b54db805a96025350308df35250b4cd87163bb48df3ea587d14f7962560daea578fa44509ab9a454d9da555bda515d6355f66cd44cd5969501a7d8cd2e83d017d0aefacb0ae5933ba04e7543ed0ce419fe4bcb9cc38e503de59a134ee2d49b8a8bb534844353f3d3e3b40363d4b7c3039a1e1d1a8496449618d8c0778dc387e29d988ead1fb42d89e98479dafb2d73c7f8f26ac050974b81a561cc1dd7fb418a108308fea1ea031a2106ef55a6b48000474a829c2a9c0e046ec4081d4e31de0c0c85d031b8613cd1344239a458045ffc4ec111b2cfaa7fb0f3c0aeb0e22fc4f92cc688f21666c7a4b93ea5115b010614eb8c21d3ccf8b5aef5a3e939d539a9dd31b843eeaa2a63345e5add236de4389359ad555ab7a064c991ea7a5255a7d205635bae7f30d3e53ba098f4a9f5f6383fe14ade6b8b710610e25ab9b44f740c10162e7c7748373e363d3836352e2a344098e0927c9921b1f1e93131a1e55fdbb7189f383e3759a56017d947bd628691942140de4de22041af79620cc04e9d30695527b501a9a2c946f723e63345ba035455a1a1406ddc9f6b4aae8bea7f242af3d53fb3e794f9a6bbf91157ade94945b23877b0b10dc4a420e57fdabe2745dd7755dc7711cc7711cc771dbb66ddbb66ddba6699aa6699aa66959966559966559866998866998866998866998866998168661188661188620088220088220f87ddff77ddff77d9ee7799ee7799ed7755dd7755dd7751cc7711cc7711cb76ddbb66ddbb66d9aa6699aa6699a9665599665598661188661188661591886611886611882200882200882e0f77ddff77ddff7799ee7799ee7795ed7755dd7755dd7711cc7711cc771dcb66ddbb66ddbb6699aa6699aa6695a966559966559866521f8791db769190f6ac77f080214d42f52e622a5ba777070cefb3f366a09f5eb4ecb0f7c10877b4b0fdc5b78f0560b778f811ca7334565919f5b84051046e05bbd5664794df55734c764b5dc195b540a7dd4be2aab75ee7a6fdc5b76a0832034e33fef7a7370d64c6678b249fd4fa17061d6751a86d27950b6cd1a01534feec6e5bffae4adc951c204cdf72cfd6094a694a677c3705eca92382ff5526ed1644af7d0f7a47cd09d1c254c9ebc3538353435a6749f6726d52f815ab62407ee2e845b3d4082bb289ad21d8713dfea6502b52c056a592a9ba8d50320a55046bdbad56bcd24a865a6ad7e7afe698b54214459344414101042c20319dc53419944e13762ede00535a9bf66134aaba6139ee0de92830cdd362b1d3c11a40304dcb4c86ad5269ad79d52624fab2862e4e6c1c89dc4fd02415e78c2bd050736c8e0ae42155781891cc8a8bfae372da2ae50d060e100090ee2c001161ca0c0dded7affb4ef094d2969a271ea47d55972b37f9ebc359624a36a1b51740167cd44141fa38f713ea57bbfd08c0bd9973ba2b85354ca248aaa56d5f712a04a274b786c94345179ccfb4954148f8ae2d138f563b3d5bb2445dda857bda59f7dd55bda3e34e4ad716fb9810d6ee0de02877b8b0dde706fa9811b34706f99810cd0c0c3fd4d34e670d7268ac5ddd1b0e2fbcc777d8c8612eea73b1a49dcf7fed38406b832b3fa42685877347eb8fbfafb0867ac3eca19567c7f3ea38aa1479970f733523fc389bb9fc1a5f9b44d66e0e1ee72b8e36cc6950a1461c614eefe6a6adaa6506a0611ee666077549b71e32bd20c1adcb7c98c1f2629285c861dda2c4307db2aa30b77d30ea430e1f8cca7d2a46ad354c65946122fe3c5ddcb00e2be4d76ec3074e086ab1f45d52a9326c3ca146428e19b8cd39d0c2027e3860c121932b8bb0f9f14e031ec18638d3595d6ac86b45aaae28e83102c319410a30877772c4020825210155cf9125081273e4f44a003620481bcc04e1a4940f1c58f2bb014a9c01a547c80c811ac2861c11841707791005a7059c348020519b8bbc8490c66b085901ed48002ee2eda028804800aa0451176dc5db484116a805155902181bb8bd0e861040d7c7063cac9dd5b2080830c520001012e7881bbf760021d0b404109d488820e776f39829a0101142d242ddcbd25094e0282b0c490259ce0ee3d6670020b12a0a822c60cdc7d050d60e00e911b621e3cb8bb480e265080083ca000c2e7ee3e3630b210c5e90542f4c01dbb34a1981819196daa2f23736b644a1a2807bbafcc5e3d12f39fcc3875d1a07daf7a5354a3f2939744af1a940215c210c2e3301e60857172f74bb3447e634c1386916bfd19bc6385093d177eacb7aab76ad2a52eb53a85118c1b77d555b5ecc262509556c9d3be2730ac0f6a07872eeef8c201eebe8b9cca5fed9a5a23f8d594f9d8def41f49b933aa06523aa003ab0920f0228b5fe5467b78e8f269bd5b2d2f8fbd862e2a072b6361862e2a8722525ecefca52d62a56cf5daa62034ab18b6820f5617eb36a99f96797d94d545e95a690dd4850e5d0071bf9ad8cbae978b2270110717667031857b79b91872772e805a7c38c1470ccc8b69e76bf5514c364461a1400c349f6846511d5c44c35928e87cab17befa44810d7e99d2abaa4e60865b31bdaacaeab5054b0c5c04661b306839c0096440f559e62daad05888446ac951218e2d306b8b18dc7d05b7b6f8a1051beebe77cc9ac955aacb266871f2ad5e5ac86851448b215abc38aa3319533e9336b630011577f71b8c6302b288a37ca11aa6308529645102772bc678cb5e33e9dec206be7f726f79818af1b5b248626581240b1d9fb1249935d7b8b7b8a0052d5758b0c6172d6aa4e12fc06205680ce12c717753837186196dfc5043b33bd8f4a6b76cb9dc7d01eee2011adc5bca706f21234a1a8342634c55a88704d6a5fc1e438c16153c600414d8ea1584aadd055e580c46afeaee6a38162b9c04a214b48461e5c7b5e2de02460bd883bc4500a2245cc1dc5d8d1b788f00788f15dca530028b211c91b138a3dc5bbef0a28b9947758f8c5d916ff6b45c51144270c469cdea2db2535d4413f2f5a394791dca34fff3f337eafdd36666276fd3d045a55af7644317a5ea8c2e21f10be17fa11cf4e64a3e4657a91a9d211c4c68466648d78822fe214d8a22ce2655af5ba34ceb357dba5a4d3333302f3328ade6e0b7413ff5b1517d4f8a5275d43737aabe79a3614232a8d289286642d8847f081543bed52b85d2e585c54c59a95a6cec70d1105ab0223b259afb29f1c998d5a922ade879615e2c46cf28257a7fbc46bb83b556dc3b7084dff68565f79a199259764d254436c0340e93e596959ff6751cd70d89de284b6cbeb669e1d6915b87793a03896a4062988795db67f8b5ecd342911b8f3d077265c6dd6efb34d30b12d1a0c4df466ad8f5ca0f31ecc9234433c019a7955ff67de46f1b8679da4477182092c1469259f77521d634cde3b8ad0811964b626089b3d2cc328eeccc6d754b29510c3c0f83dc076ae1ddaee7912414511be4f6e6869919de3813bbe00783f0bba5e97d1b4776e1c769e169a7d6bb8aaa88d8e8321234cdf09a5979b792fb5e906d77d3bc727bfc5ec861ed34936af5461453ad62f5a67a38ef2972c1f7851f725a77bb92e4c8ce6b01ce3eb2e4382df330cc659f9d44f1bc3ea22b24b665d7fc70f9590886dd7712c56c9a334056d5e64e4e0e4aab39a228aa442cb85aa779a486856499ddee2b4fa2a8baaa69fda050b486b6755b499ae4053b1c7ef79e44f13c731451f4446a9058dbb28edcee7df0db4c5094c60db190fccc4ce32e4966e09f66747ed65ba2da86f386b40a488614ade05e0f3f873d0c7ccc7166e644264784c6976087811ea665e1e7991a6812c599375f49699291223ae37e18477a187737d4b62cdc64f48aee8862894706159991698f65bf71db7f5d089a9f288a62d05d659088cae8b0f23b0dc4a16796a199996498f723370f67f739d3bb261ea3c498f6811f36312ef338ef13a30c31ac6999e6955dd85dd3530136b910bc18666a66d7e1ff147099f9d967e20de4b832fcca30beece24e033b8ecc3008feb5b291f76ed87f1867dec5400c8cfb819a8699f766f8db3ef04fa228e54d6b298a3352701e95816c64aee88b2ff33210243990bbf8b94fe89ea629289fe78be28a665d52228a7a5d5f5d7756bd78cec359b76d19b691d9cd26d3aa4ad9a2385384a88b7fafc44caec4e4f77d77b593289e299428cecc9cd6ac5e1d6444271071919920489addc791e46f61a6a974da448482ef38ef4b8fdcb2cd33bbc77a15c5acc3c1e7e71c5114458c7e94f29240884eb07519978124e6be30ebbe214d9aa294f72445f1cf954ced1c445b605cf9dd52d31e97f872d93d89e28f28aaf7bce516c5287f5efc426aaadc1169a181dcc661e59b8f43f39699094ad2fc362c2c43eebe8771dd8c288bafdc32b3db3cb223c16dcbb25c82f066d72c2f09861f489a2159d3838804f733c3ab65a5c79938ccb86f04d8e5c090343d53fbced3c02b0230ccca6d036f1786a0196edb098bf203c1eb5d8dd44acf0ccb3cf43aeaab74921d5108f0d7e1ac7bef7aa197659fc623bae22bc3ad33333224cd30c4bacd84fe298aab5497a2380305e8498fc80acfc324f61ef3b6ff3a4f2b4fa2a857349b382f65faaddeb40acec34cb3bb181786de2d3113d4321f44549864c7997f3550d33c2d34cd9328aed4157d515c1f044f861e87b1499658975d8efc40b7755818622488b30fdc2e289a82334b30c4c8df6ef6d847e293488aacdcc07033b18bb1df6e989d3c6062e42d390dccc0f73890fc93a80319487625c6be2bf1f619d9fd88220e64dc6682af3deeb28cbcdf9d4451136d20d4aef086e073f77265f77d188653e427116900fc346ee3c8efb9ed2bbf0e3405a5c8c7a64f6fb95f1467d47b2a714451845fb85df2625e784b93d4b08c26aaf281d966766477412dcceea6cd0ce11d191f445074d9931863a1c69118c7793803e0d5c82f2f8631cc0b71c66100241ff4b2acc39fb981f7d32e00925e17deffe7bc6f233150648192331f0bbf0fec3edc71ddd3e05bfa1155e0bb5da79959f9e0c5d9869114d8bad7b8db6998676a9b87652751c499e8090ce4b2b2c361f8ddcf304d1339e1699af79c87912679bdae0c75444d80e0f79a09661cb88126178ae2797e89239a00d8fdf76518fedf3a2cec4a1e444ce04dfbfb5bf9651e9899dbb684f78119e8e18ebb0f621c9a12f8c2cff4dee432d2cb4832cb8e8822f06df8ebca2ffb30fb32f2823237222ae64672a5569a24fe3eb2e43011042ec66160987d5bf6e4dd384ef480bf1988b752c3a54796dfc54ea2f8891ce085d7c4ba6dc32099995ac89d441146a404be98f926d64052c3e05666275124891a60625cc9919c866ff895da056b444968e45ff3cbc8af7cce34b1264242234b73fb0cc3ca8eecb22f131db18524579a198637cedb3cee33dd181172d9a69158d8755889bdf28bd82e096219feb8adbc1c3649066cf731486e5d098297bc99464304d6ca8fc34290fbc2edc3b47b12459b213c7c6f793d8cf3488c651e7612c5f3aa41f8a639dd94ab6164c6911a18e22f3b6c3b89225ea134a2b842af4cb6fade0bbf0c04c36c7baec3b49328cea8bfeec8d88822fe9cea206342b329d52a1645754df51046b30a4d99462aee233f8c034bace1ccfc0e9f4491f352a615651611fab410cb3aafc43a327caffc14697638d44caf23b95b625fa8ad5979b9f233b76cc3fe39f44fd39b443101fb03b5cd2bbf33b592bba5a79d44717b2a6696a6569a9cf6e5d769df9f44711d7a54146776a9d288e22ed52b8a386b1920a43c79efe5b42735f337bc5d75dd32594a9adef7759b477a19900e3298f6364cfbbed2dbcaafdc3e8f3b89a2286ef54394dbb86ed3b46ecbc00e6bd713459925286fdbca0ee3b4db91a14786dfb99521b769f7bb7b4d2ddbbc93288aa209cdd76422a394098862721bd6691ece4cedbb1a49cafc2084a6e152c3c8efcb8cc818fbdbe1f26661467e21cea623a7ec9a77c37733316ec325f69d445114457127092a3f2c31d004b14f2b3b9c85275114c519518c9293985252e6cded6a18a761da8643ae04372fca637cb10dd3bc0cebcaf0b34fc560863f8cc43e9233ef839f61e4e6114554896597c41bf685f8bf6b6253257febee669a5e586a59497ae0793fee7260867ddc97fdff4782a99f11c4cc6dfbb4d27c0d63dca741e9b146809e34316d66c7711dbe9f1796186fff0bd04a6de3b810c43c0dd43c0d83527a9e19e2cebb1ec8dd320b4f417458487ae5c5dcc5b0ffb04e46e7c99691182cc992ccc807414d03e25fdbc2ce34b992d4c0f25f1467667c4840323efca0fd478238fcc80e632ffbde73f2755d893532f3b807376cc39a6878d3380f93d973e056961893eb65e407de72c34af0fb323c89e28e28aa7abdeaafb966499875179b970b35ee6e1ca95d140714629e466e1f6210ecbcd0ec4ea2b8fa28a6bdfa28a6f0e7233130dc4ad3fcec0bff663035249a17264ac22cc4b6ff4b7a9de971dac7792920056020486298c49c77c1ac0cc199b2a4996648861fd785a51992e4a67d30eeb6cd7b33bc26eec06e0b4a917fb3fe8f0c921e2dc4f0f758186edc35bb72bb783e2e243d8fe46e187a6057062501c98ec31e6662d956729f6148340f7b532b338cf34af043ef248aaa474ba2785a57cd872fdbcc0d6f9ab771dfe661e4295dada238a34d54144d26511c62e741cee4420cbbdc9ba636d1e89065d8799f1762732b43cfec41cb4af082a6f675e14c0e77432fc31fe99137cc36cc3ccd685b6a75cf74e79b33456519514c5159145129b407c77bd2c4c26b6e7f3def13459b1b2cec4a0c9b1e199add2d3b7cb2c1c80cf348f323b70fe3b0b69d44f1b453290f35a587c30e6319c8811a4782df4914d57b2a8dd0905888958fbfd2033dcccbbc9328aaeb36cd346962d7144a07199107cde3b8ffd2e3beb2cb2ef627d17425a0d34ccdf330d6be0cbb65089e44f1d7acaa7098e1322febc28b370ff4be6dbb27515c2f4ad526028e7821fe36b3cb384dfb9ba9b41a74c97ca869d72b3913c4362c34b3932862f5455114676848aaaba4c7084aeb1fe26766df7b21f665e4d669ab7a24e4b22e2c33eec94dfb3ed2244f5a14bf447dd01c5114c59dea1034392d2c31783b4dc35ec6992751349d57e84da28866efebfe765a89dfe334f071b79d4471f3b83023c90d77e1f679a5697e27515c51a629a60bc9f2bef638d3b6aed3c2ec248a265114458e2bb3aecb409233c137b38fcb4ea2881fdd3810bcd704bfee76190966dc491437fedfa6f5834471c6ee6b7f6e56513ced7bba325b43696d0a524da61f1901b0c7a675a75493298622305776430c899411808896cddf2133e9730030087841c090ccf4427feab3061d7040400e37e0704366fa130d36bcd82135bc1c000dcadb06036439d0c015e085007600e69a32194048868300b414a54b93fa42ba7cd564caa2789d9696ff05e065861d6458d5bb0e0932c4d24c261c4634b81c0000d9a5210602c0a0e1df0148945b961fc5beb007e042015a18c08ff58386b0a0e2339f4a981538cf002a789d667d0c69d57a801ea09699b48f724fd21484e6a1b72d99097500516652f57a4debd0d3e0d60c62c84202d1a32eea23862c5d6c20a2200079c1d918c30e1a77170374e14156c0e2c70bcec61847a071eb2af8e8d1a2824b1240921085b09004107749427497246e70972190dc65089b358006a4e15603de70ab0140f09114dc50220697190810a4003204b1425c66d0a109eb561346dc6a02895b4d60b79a50b9d584136e3551855b4da4e156133c70ab8924b8d58414dc72c2c52d276c7097bdbacb6e80e5848c5b4ef8b8e544106e3941845b4e3ce1560398e0961358b8e5441a6e39e1865b4e04c12d27a0e0d6130670eb099b210390810007c0c3475670f091152fae55a8643328c64deb143223000043020000d310002030281a0dc70322a9603aa6f71400025eae5cae66a14ae428c931658c31060110000000000000800193871d18736e1c52e850ed4bbea45651fcc66595e89cb1cbfab81b79da605983b01a8b33bf149df7aa273eaea7b403745bdd3515416b6fe2fb83ba1cc2854627bd8e6fe889e2101ec0ab704a071395f208a7f5587e00e7555ee79cfbefea3e87453db94eb2220a55a3ef622f837ecd6e66b0d6c330279e540bce314e4f5f2f55d4e2a1897541e17d2857df82c2acd39b37ca86682e00dab81ac584cc44ab15f50db89db986b3d51d3785d360a59dc3536b6b8b047d4337f2f88a1753090d61cd4d9d6220976c2021ed94b9b617ebc07c414c8e4c1963f5bd2a8bafbe86fa9863d8aecdfcf0d251d708a44b7dc55554bdbcf3ff4f9493030cccda43160f33218f44d3dd7b021bc53c73c4bd8619f48eef803a7de2b90199baf834e0d2851f7089b43a2689f4cc31b1f325b0d75ae41c0658442184a6eb4ee997cc9184d44ea46ac405ad919e9f9825a0c7f066df1a2d9d07c33527e89a57e66aed7b1f488b7b17a0b6ef16efbbf5fb6ef77db771dfadb9efd6e67d37ba5a0f9144dc483140f16a82aa842d1d56ec424a0d05a3f67f93d2fff00ddf0a81d945d96b1c9d7c80dbfa5c596b675a671ae5a60b76038d7036b22963cf05cefb7cff8a9c203c7d30718ac687500f1f39594e30c0313eda909b7bbb0541de830c13b1ae83d818d50d3ca3b8e89790fbf5fe17a14f5ebec3f362cc3c8c407c7610a869f0fda4ba1d77d3ee7db75290ab2ebccbd63ec7c472c163faa1d1cdf90c3b53cd1d021b36f15431041c54a01757d42249b2a2b0b2a12b97e2d424ae50908ce27c4d16bb6b307a9cb79621acec77576edd10de6b7355ec96d1c03ed477ef424586b02d785ba9aaa64df50a3481f2608240a2c92394a024d3a555d1a9b4ab0254388ec3611367fa1f5b6a677ad4e68f53f799a46a90a8326efd8a27458abd092024a2f277e9394b3e68f97d520314ba161236642adb3e6b93b73b4071f69889b61d305441d4063641a94991f8f385b7a5fc05d10aa35b4cbedb436e107ff88c9c5a98e9199d7b17716a61bf32aefdb70656d103a85eddb81ba97b1527da7bea21656781db438dcd7964b073ad172c9bacc7cd8a5c2a9275a2100bb5fc283eeea4dd0efff431f96e07218268d0a13ebec4ce96b1fc387966ace525f35ed357a91ff8ed5105b4af3757c09c80a6e7e827da9eefef5783966d606fe5fb9ad453edc4446cfb67fdd3c566f3f5e8057e8124d98a39d7e4d3fff96e514fa73298da50f51eb890ca1ec93bb31a3c02e22cd2ae36ebd6ceae5963870ae0d6c17d03c65969e2ec730226ae2c684313e6c88f0216fb3a01b632c88a9c0ffffb51fdf34d066ba0ccf9ab9073357bb36ecc90206c6b486dd2236818226a21b4b49462025bce8206b675cad4475335f4be7926f620357065977c0a456cfcb10152bb6133fff398974b2330a8378907599ca93c85343115a5aa1f4cd709f5ba8a26435bf53037f4b233976df2dac5304914ebf2260c6da37b3e81d618171a678e9130299d26e6f0299c7cd2733fde7bc3f4ba3940deeb7e1c64601eabc4f8b62498fd498b8416089998efab2b463d461e5ef17a8537ea426f94bd54ebeb351cc16e3f4cc9feb861983576f9f4c55faa544784071168eb1bb84e27405a0afe30b34a2eece089f2b049bcee1c682c9e25396d042554f1bdcdbcb5b99eba274e92a9c07979cdb4c47c515b4fffad2c52bc3a5065a0a30f99c45463a0d5290806bdc4de7576437c73795d37aa2aed384b2c722e611eef82bcf03d7df32d26ebae3d5fbf496820e7ba8731329823aff38d48a11213d2170d0a77abb384010c172e68f222ff99e8a6d055130e5488d9651ccf4628385be1e6e8778360cbd74a3c1f96d4781bafeea7c881ca5df9d47ceb8e1ba899e55c17c8c41554b93e20cd429abe49179659acb3b95eb1c544ed4a28de678851a15c46523af4a7042b6a978f6abd2b3c36fa1356babe8f947a5eeac90e8e44916639ca73f8505d72ed625faa9676763b04e433ac8a8fbd51451ed943d4be2cdd2876eadbef2aefb4fed30164c5c6164deb854e5c9c473e5a06d8bac4931722178f11154ba5239dae52390a198e9a0eb08e4c980927f3c8f3ba182835f65130f4a4894f21f851baf1a76046c01847e5fafd40130619388014f391c0816ff5b3926dbcb05e85e264eaef2fa6558df039b63597f1580ae3dcc2860792bf5489d0527ae82ebb49ed4326129d50ad6702a74e235de4f9e8bc6bae8cf46bb59615a8c00dd32c3c4d17ccb0b82288c3c013aec24e13dd11d1a8a503ced0c47dfb78f916dd9e5507b81a1e9fbd372ce0450d896061a8469910eb9658d4ed6d2430269b0f0055b0d549424b867f10f7795422489d059eea8b8d21a01f2f5e1ed43f1d2a0e2409241988557e70779f0d05d73f60e2c80e9000a78e7483de8bb9366fdd7f248de66dcbd88c381986818de07b69bd7dc44cb0ed6439dd6e52843edca2570000b0bfd4e1e5714303a0f268548e6186651ad19c651207455602cb46e0510bd871a771e60978606d4b52230e839eafa0e835e3f30c01177f8b3c0c31b7136052fd7988d74acd1e422eaa49b0726873d09c7009fb846f0350111587fbf9459d462001b60c0aceca0444c3af2f704d6f6f43d6c7f813e3c3372c582179f60d576ac0253cdd0cbb963a28abc81f84485226e2419060006136d62fc7e800e4c00bb080093f4bdc0e17efb191b8b50463933f76eb412322126073771c98b55d3d2b7715680c4b7f005dcbb247229968020c2fa8626596340d6deb00905d88e6e8007e4d0684ee16145d2f0c61cc56b7c6734fd1d6a9f0eefe8932409af6e891e0f03d2a20965691ab8073ddd0d20bf2b18d6de5490652a819d10f02c5d063b2600550c2e7f85e10d1397feb74434bd3d0c480cc1e8fd2882239c77787a9a5605cea3e66f5d38a38c86486c05f31c3c1d81893c130f354eba25876c15fbd406180715d1c7f616cf8b423a3bf67dcecd44b82dd43625cd708da3f7ac7d6eedfe8e9b61afc2c4eb46d3f2ffa93ff9189360c42b8c6e6312577ca0d7b4a88c99f4bc8d75e0f5eb76029092e2e2610708f08fb05168b521ca260bdc142970f428f1cb33f8fce683a23621f18255bd403b755fcd8f89f85ba309ca39e8d99bec1cb3554008c7d3e3ce14a6e24bf79d407be26e30dd1f68e2adc6fc73128d2277c093f20724ab47da6f081d10dbf5b7776a55ed3fcdb5b1a4b66de25fdd3b6622781fe3f331d6343b2e63a17f00bfd3f7ad46017e99ce6236952b2a727f563fdf221da7e14d8fb0d1adf4cf991fc1be15ce1a0b0d1330e9d8b330843597524c1aad52f55cb5389a6373dae5fdf6742d68f7d9abb9e0ee1f6e27ca18e416c826c13bf8f6bff81913f353d3bb2fc5ee903d43541d86736cf2dfdab37ec6151370b0afae7cf860a775ee16503d9e2a874a1541e09b7b469f53893a7ac87b7b236bd7b0bce0dc298a2be644460bdfe140695bc2b61f797626dfedc85a5eafb292d66004677e73274ff52755daea4b11f009aacb4b8a3a4776329d8782180a9544bef259cabbe76f1a1737acf2016d93f44844d73c6e730788c5184f2ce315be4d9867c00501842dafe08ced077f89c0b7e99316ca2a38ebc69d79b0ceb8778015a24f76733812b711834765761091cf1e9d20259cdcfcd020e5e8cdc3ede1c8f4d0ab1137a5a0cd04c037133dd091a78d58db0726c2c08861a73d7006218668cac1cfed81433c07168cebd8641042c3f9a2dcecbedd1e529f4de960cbfaaa9cf8b7502f0877f6a4e4ae3352000d8398e87fecc8c80b16817b9f3e510fd165cfee35bbc5946391643fa1942fc3b7c47dec57d8883b041f4b174ef66adc73da6a64ef6ecde4c0e2f3d0b1a899c11eca5e4bb4df48707f64f5f1ca4d67a78d21c59223df073e0b6f097a5e75ed075ef0549439299cd146f7510dc61712bdaa9a7d1cb97cf5b413fb3d089ae3792ec9568fc6b56c3317d036cf23863f36036050aaf16ce7098df69da9df70036d051d673fdf5b552f9540ee4d1d5e11ce4417a1a20d731fc95aaf875a2f0cfea7106e5337b34dc8c72e05f6e60e2e9d2b54fa037912a622bf920165f3ce3b3d67f12fd92f32e9e9a641871cf0b722104237c9af62ee06960c0ad4e244a9642e72982a878594280e23ff6cd5cbca7ff218ed83e621eb4c2f9c1abcd5a31473cc736e48a2799ecbd7379c06a50df101ea2d8110503cbeb3cf22f8b32dae83ea88d84b76b057da835d7990cf6826a0181fd6fbfc846b037797927eddd3a431ab99a3d03d62d5f3255bdf6ab6f5c7988dd5f2b0822a088943fe11b329d6939d08684049b936fff123dcf3e48df063d5dbd754a4cac7dd2bb76956abad1873fe09e725f3d5356fca6b8ba3ae09b6a5f4abc55de26306b0d9ce10810be2d1d5a88c58c554b4e972db7f0d25904ccf7e00e7375c0ca091e48891d0b3c1079ffcedf874ed36c411b7ab8fd7511e5e6863612aa008d6f798f61bff7bf644d3820ed5eafca7cabfa71480e0006854cd1e9abb4b1f5dd189ccd613ba2fc53ee3a4c29786b9be9cd56886aab87cddfbc7a34c81c071faa5dbe87f0deac0ec68f8f38b00005752844c6eaf9e9e33fcce79ecdd829c02b3b1487741e89d39033aecc3a7f3c7591227450b2f577b9cc48ebe109f8fcbdde70e0562a5170e1828dc85e0a05c23c8a500872e227fc49efb6603e5038732fbdf39b47112e22e5c83933ede118b11d3bdaaf5c2dd935bf8b8fb4a011fb8d1b4ecd493295c82b9665cd8a3f28e11d656f8e834a3417b3801d197ab1685b616ce14287b9b51942be4c72e1252bab5c64d6ff5d9f8476b4ed306c9722c72d846be15f4172315971c7486a158cfad4433592270835276626334f67963ba61cc6cbe4c3e97b8bf85c41596b8d5d719c8192db0d74bfa5bfd6c80d8af42ed572aa696c1a16ca7b38beaae5ba3e4f99b80e3c678ff90b62a5ce03527afe2a2bd1ce9098b35f94524431013f66ce4387cea8963a44730c2f7217e64d6d958301e3fcef4d9bc2dacc5a0f054b7ceab2c6bb8681fe543805178119bd54b241719b171dc222589774c374e25eed15dfbbf5fd33e9dce6bba7bf7357dd218d0e2518518738418029b34ae4d7d0d3409ee94134c44714d6b1b8e5defab48e9ba328724e88b5ba8eba502592a98cd85833daf2f328a716c3680e262b7b065c823e923d5d06a9e633c7111bc3eac9ff34e8b37e440212f68f2c1aa9855d03b249818cc943bf93682663de55dd71c31e1faf0aa9657494f6e0a0e71e4bb82a114d309366b1218cf0e1cdb271781976ad4aae4c8bfaac9f4732544bd030eda312d259172bfd45e4b05ea90fd24fc5da73f69c489ee70553782bc7991994adc5eb43791d1a99861c60dd38a5ccf100901884f81b2d0be941f47683fd59f983ae376ef06396ba1ef46e7f37feb0764a0be71f246e34bcd9da617bbd78caedc00e180cc09b2ad330b40348ef773ab128ded1835adb918dc979bca29afe0c3014e54c23fe3eecaa7c62179c93fafd4bff49785f9ef663b32fee2df08ab2004f73e9aed595ad0e86d337b75cb0d27d51976df10983919f4b9c37599020afa2461bb402cf2469166af38628bef3745a749afa08a2b4511e792156f08afd4a4698e85981cf9eb227e23ed95ee1df6474989f97f6ea144467270510efda2175f1404434e0dd7563e38a115c3f22e1bab983b21225722a2fa40216f6252d850328f15b54745a9dd552f0da10c33741aaa280a12110b9fe6ddd6fe084235a05a02e4b729778a03d428e1b8bb9a9f9f7fbf0a96759c1b1ce808beb7562f7183a1ccf7a750eab8734bc42d40f6ab47c114d132778016de9bd173f1b61239d2a119b510e63d36e87bcce7fbbe1be5bb828e20d2865919652e1262074d0e36b0e5e19f7acc95e345e4d5e62cb8991a84e488be634e76a51a626d4a7851506cab593e25ce669da0125e248d58dc281a0a2bc651e46439489fe38f034d30ddde524622e9af8e986e054bfeb16a1b6c3a27b35845fc75dfdd5e9b6fae10dfaf8285678bff01d784f87c1f0b067a6d9ab3144053dd99987e0d33ff779a32f93cf2fcec18abb274b7bba52c682a5945b52d6b02eb90d783fdbba3025ed369d96d10318eea2eece1b1e6382fa628a3d5868f3965cff446a2db8e0f6230899c07a3ecae12e985e4626b7b373145faab58f7a227d96f4385ebddae450f285e323d94b55af4f00cb056569d5566a61f83f1d0348d766e54cea99f8b9394e6580693414e1ceb345401b3586a4d3b23b26453f2de28193d48a82e63f4e28a9c1279d2f6929944dcece01af7fc8affe85287950989554081d33b2d26e13e98c171332aa14ed9e48961963c324c46ad036994170cf3aa618ff4a8b54109dce6b9147cb0125604984efb2a3839402b834b85858237399b41d66848824d79c53cc7dc76860e1640565c0242d5ed67802ec0c2ebcd920aa205d550a573eb583e081e3e9b368e7f061241026088befe35a2f6ffbb450770330933ba9e7eda95b98d9d360db61ae4bf7205c1db1bcb94f5f3dfea2e9f6139067e4eaf52db62488d6b32dc33537ce584d0f31aedd03466b78f8c1da1e7f5083078fd6f0f083b0318e00060c108581610461631c010c18200a03c308c2c6388bccfa431516d30d53086634a4f0cd0e38be05638461c30031181840002b0608c38831e230308000560c10861163c461600001ac18200c23c688c3c0000258314018468c1187810104b06280308c18230e03030860c500611831461c060610c08a01c230628c380c0c208015038461c41871181840002b060877c95d12d8521eb7706e33aacdb16c05b14d7b4d98b5605633969a8ffeda41784c1a8750ec34b4b898346ea1d86968713469dc42b4d3d0e268d2b88568d7a1c5d1d4710bd1ae438ea3a9e31ca25d871c7753c73974bb0e39eea68e73e87618421c4c188710ec30843898300e21d861087130611c42b0c310e260c23884608721c4c1847108c10e4398f4208110d10314c2f30ece084d1e18232c7a0ca06588d6b53d03b537c08055242718d1e080114d5f528bae765ead5823321b42ca5c64e9ab48078a56323994e6e97b20aeaedcb4d10764e980c4084d094619e1830024be48874ec39c25d9583d419605214f8d89e736e94aac8765c4707b167626700b51f0ece4625dfeb0b57e06d3a75ae357bc46e73fdb0182929f29e3616095b4522359cc12f0d326e8130506357bafcf50aa39ece9367072418d7254099caabfd90ae85bf28efd7ba7dcbb024ea9b3dc87179730204d7bb1e9deb854616b441d532df1e3f7c059dcdfd16d9a77c0c3aea64602a0b4072adf607edcad62603231c77f4e673903f658f71c88a018f31172251e76ec69f2d1b392d559751e4a296ae4ed4bc0784cd2df6829985aa7332a71f488611899048269db7606906e570fee44acf5f466f8f4bc7d818d70865ef75e81d0e16593017e476701d8cd38edcda0154f59a72cc48f6c4b03fa36baef423b25195ef1739d231bd5bf1acdc93776e45fdf2f861f73ca0bd195f8bb362cf224c5ab9fe1569f84f57d84bbd84f48a1d630fc20e8a3184096ab1ac73f29dc7997c26a1c69ac6800a8c12ca07d7da8319da21d13138af4ce4bf69c63c6348b2054f9639cb9df9e7fe9d5b58198c2bd1c5dad0f71570e480d86984285a3ecf754a7ee8e50a4f4b5178ca6f67fe67eeff744fb8ae06c29ab679ccc51c43f333ce23bbc45f051a28b9c2d697f1e85166e43f8fdb3dfc49ec167903c9dd014e93c835a6d3cfbc758edef50b3e737ba99a06107024412dba764c51bf2de04d4ee8009383452a049e01776d7221927e54d4b8324265fcb524beda4c849e7c0f655dd2180069446c32390bb5659c30a39cba69b0cdd2307f917e85bb73117429ae975f144f50a5f3f5e7e1a2c29cec5488ff52e58ff25f143d1a691c1f9c5f253a19eb60914c9a39aaccc33c4b7a30c9735f19e5bb502522b6c7649f80cd43b4edf93ca127054a3452489962b21b05bbc53c073e184bcb635f79658b3dbcbbd55fcf472f468101154d1a0a917edea2d177382c0a5d710d344b4ea2bcc5d2b58d123ead7d17f15054efdc18f34d1867a3cc688f82ad7a62660122a0f49228ebe37d488fa748ab58a1196f696acd13b7299f712b3f505f4118896f51a5a7a68d100d5d7a294d5cc9c7a9e2e95a8bf53e8b00898e44d5eb2c8868148036f743a642509999a15e3b680a3b2100cc57ba59f4a13f1e8c71f4709167aa14b0d5462a258d059b89781be55e218d1db635ec3892362f9c25f6206ffb28a490a3adeb27ebce5402c1cf0b60cdbcdb1bd25352288d402626d3f3857f814692aca1e2694f57ce13e6481411b9454140bd42bd0aa90673e2c265e1844d883ae70684a3836b580972609fa7316d68cb53547934eda642d6b02781e740405d2c2538428976c0f9b7c5bf0edad268bb6c5ae2258607d5ce3f03a4ab63b0de7032f1abaae8474a45b61a5271654d1c0a2c070cb1997aee2a617677b37deb0f41d678f6e0eb976090f639cc1c2a9566042095e6523174c143e084912dd70d147157ccb65b18c572ced2aaacf8b790bc0ccc9a48a9d7f442f22d00632a739484516f7d36678125bc4278d456872090fe49b52e7ffdb900f03c1bce80fcc67dfb79b06d23ce9132b12bc597efb2818ee566dc4a7e54ff5e9e1c307239405f0ede28b56a3a239a517e5982128e1f574e583312401c4f2fd9a182e383f2c7d9d9ea1899b42085d45c3a36603833e0b22a3e4aaa6474037eb6a01bac570ca01f19ef2261c3ca4c8a44d8d5cf1006a8bdcebe46727b3bb2ce5c2fcb7bc2c4b997fe6db27188ca5f14f7abe9371a477b5e7bb849a2b624b5a537a6758bfbee1875447b201d489c8281c3fe9f119fcbf9aa3bc1a426683e9149871e0c9e9fd32bc219aabd73c5b72b1c4ff359ce69d418320fecbdacf43494e70734c6702601ca763291a1ed89bf9a734ab857a2e0323c6bdf3c4dd3dda8f4e807aa17a4a5472480443515c7ce9637590a5adc689a8af6a229aa041fbea0494c802b2235d3e9cbd78ee24239317441f05d2e1eafb1603f5d009574801665f91990dd4fd55b19f4890c25b40585421c23a5e626983c7d2184e719067e882a73febe9aabeb3cb54459543f3df1bdaf36c8f9cef4ce25b4cc8dd51a884413a7cdc6e3f831048f306c727bb7704dfa92c1e37009b1d250577c872ff7c56da1eafe1002f976984e0f897799159b82e47c7336707cd082b0ed3e15c4a2dc2f3d018904f32095ee27c8bc918847a3f30832ed290f68f75441615f351f4bc3b4c66b7b08e5419d7ca1c00efd911a7edccd1a13cc1d8c79cbf5b876d98e336e861570163b703f53f150fe5aaba5a523cba620a5bf37dc6e03f580371224e0b70ddd7b8aae6e1e290d501dc6dc8c4a0af0e1fe1b2b462358a3c6df9672b76c8bdd6ab2210bff66501e6f820b6e553a4f71c885897fe7466642d505b9b2ccc11c1b725bef53d8c8257365020a249cb8e7af1000faada465b0f6696a08ef1128423e9251d8a26c1a51b3c4f73caa1eceba34929fa7f7a06d7fec3956b71a65d296c50ef4908228296bd1cf434a604f878d3d9be2a69ff78ef8f6bd889afcb766e89da09a9216865df820872cc25957ca0bb91e0bf483a9fcc4988a76275285feb960bf5dae711ac510df9c6bcc41f5f64b02e3898c4521e035bcd56db23ce6fd2412d778f3bf8046109d24e6358b9d250b4d3ac3d3cb9f76d783367e5bcb634b4a2616c162cda372c1bc92cb8d7e91758de4aba62d4ff1654f900b0d10d41e632ae2368694975b606fcc9d929441cf871b41060bc818d027220ed7c4d232453990f401af23c7383bb24101be1c493c097eb96fd6c2680f0ee54d86449ac42d6a201b32cf2505aa77d15ff6fd5c93c05cd426b4dd077fcc8db5347e04ca44cff5fb95134e17c9d4a655cb03d990b4c971b64b3cb64038f9705f17d18977d201228028628b5c37b1d58183da75cfbe7ffe6e7fdec57e90709f1ff8fa38f986b1a61f51ce32568142cde0ddf7d5ba07e03057ee5a431ac142ca49fb23e769273f53fafbec369aaa9fc68ff1cf90efd9fa1d7e8bb29596679bfe593f34616f8cec970870e41f9b5771568207470cd93c6739c6b66e2bca49322628b0b573c64156c20dde187680ba64dc98980d1a72fe4595c016865c8b9aea82dd070ec1d40217c9b8233ce354faaf662a03cb5e6a9f1a03ec1fcff2a3526bce7616238ba9ae91395ffafb9406e9571171778d5badee2206ad41b58ff4d729b771e3ecb5eee8ca1288801b2c73b0add113c88088cff31dc3cd100cd9d33d414ef90afd5c7a6e024d7da8e915b539d9c771fb38b605141e532bfc897ed32e7cc3d51655eaaa58b7e7678ce3d776144b344d3633552ae38f1d01af85e421f8b9fb0641b3cc651475e8a9771979a6e8da3523c37783c305caeb7aeebff80a5a9055447bad95e6bac7fea56392b8ff3aed4666d040bbbdf592c31c40168061cc3fd9a543e9c38daa7c0836934cc0d6f593c58920e6741800d6af6e5f4595047ef2e6c9efbd49c18f0a6dfdd5535a61544f548d668cc416ee16d66a1ce39c9f525c6a53d93bedef957f34f33b6dc74e075a9832b15c17e7f60d3497891b8b37376700ac02e9f95f931e996bd5b3690fe9ec02ded94253bfa8d0eacc5701a8ecd7dc08e888caa99cb7dc1665c968db1e69efc02ab19603bcc0fdd39f656d947f52a65a0f3e8748caed64de8e14605f561d54be58ba22d64d4f78858d1ed9847664db403d1af5cff524538cfeb1df067d197ec65d150a37bebb7ab107a2b639ed8316e63cd6d74017fcf3181cb487aebe7476731ed0a90fe8f6381d3a508a6f79fb569fc0c3748f369ddf1d57c1bd5e73d98d3b1541def7cd4fb53f01e8e77fb01efd8dbf99a75f26340e4f8b488c8804b71503ec5e59c7eeccdcac6248c62a54149ad67a8b3826322eb2205d65c9f95475200a23e275d535784ae3b17e3705ccd16039a154819f69c963bfa622002644ad6f90443223d8461c05ce55d4a99bbc1f3c1e3677cecb0b469eea1996d0b7786e02775dcfb74a5e6cda30bc531eef2ca8ca266532e032aae487b0c7ac7f4a1a54d47562336e58c4670b9e44e95934d38202a2810dd785d28936428d3ab814247033e903e9ca6daaf17649a97ef0590c10cf434c63df8a89d45c3fd3e1c751b379c1507f969617b1c2b1d1207ea073941079bda6b231c333e078a98205e458fef45fb1ab9a7bf970e0fe236270aada8fee8c637b7480183b9c9470cb41c0d8b7833f47646836d65429e0839acdacfd50b929e312b9ddabe8b995d0f8b8b4914442a1f0c8b44ed42f9a3f4557046646b6714b427e7246b5ca9d850cac17669832bdf16b4080240dc3ba3796100488af39987f3028cfb9dd64f697b3d58e9e4e0cbcf8a024c03bd8a34021a72b0234386805840d167b49d244b3e6d80266c2bb36bcffdffa6c2b5242b681d2cb3b91004c14397a5989d3fc318ecf9bc6bf35a4906a72bf444c9aa5dd54f60856e05c07b7d69d65e3dd8448a353c971568ca0926b8ae761e1d79eac2ee5c1f30918090fcc5f7c9440fadcdcf7d4a9d197cb061cb4312cf2cf316de94cab01cd5b5c33881f351a99f5fe646466d5b480c601b298a9acebd01ebcea4fa9af0c2845b642ae64c57f396554f30accd33eb3960e9c9a794bd79301cc4b0b93b4e56e5e337c2e7dc2507adf479bb8f0c740451bfce0ba69b657117d4acdc009464f5ca00a166849dc36bdb9a0d2f4066c9b02c9703005931881fe8f7406bf122ee5053e0f745425524a9c0c39c1abac7ca129f0007c141fd07e99df24a6b24dcbf470f23e34e399379c582be28e2fa4171bb6f179afc63b491a69fea1bd12e5b28e5fdd2774103f2a1796857743694ae8683707818462a030f6b1b07310b9b0997b33d494c6fe9f93ee9a4ea3bad94878605b2f8a2e49edb44b5125fed41662f6c4e9373d2ba86aec2246617c0e72ab552e92974099b176cb457e0f96cc93505d486b54de00db27f79fa4f2450a6767853f0fa0fbe0fafd01c5c0b98f7935a4623f0c4a5103c1609575c3e4b03f906117e17d87a13ebf716796440a07805c1ca2d4a93a345a170ced648e582bce2aa29933f2c49cb1d8f7f3bcda6cc2c05ae04855de509c205b11994942b267a4af61d6660c8ae3635fce8e5ac9a884d7e0f8bac61e1a27aa469b1e0e9485c6e845facf11aba897d41790226a3dc8a43aba56a7c40d32c36e19be6ed6856e158fdac979e11b123328eb41d0a0705b6366a11bafc6c2bc88afda6ebe6f2362d1aad22249c2777d714928726f0829aab47cd17b2a18ab42042b91b330c7817593983ff1185e9438051d1bfe6c6b3d0106cd2edb47028aa26d96b487f285bbefadd9c250d9fe318ed71a2e4475ab12dc964688efc73c6f984415723c48deab08bafc0ca478fe7c69c7cd807f01d9e96b76a713505a1436c6ca9df6683820f00ccda6496b2b0251acc705f57255901fa90d8d57edfc663c3689476d39e2caf9fa045b1067ef3857719894a7e933910badaf3b803d0a25016ff8ace85ea1fcd07e37d38c0cacead5604d4a0d44bda2691728ccb76e23f38a2348a3ba255c351c1c2b0fe029c951ad197ff574b2e89d2f0d87a2398cf884edc86adde45664a36aa1d658db8c5ae8691b1f0e147c4de3c88fe72fd79a2f22c81b2102a05552bdb618dedb367c52a27f8ed15d67afda5a49e82901c6774d3ea464ac0ac873e5c29854bdcc14de59cca2e2ff26df3a6a91835a56ff544dc5d263a3b50660c360033135b83ac459b886f40fe628e200276cbb16b475c7a90365e71b6cdcac00d34fcdf18b12736271a51cf18a5493341c1210bb5d19f5fa35058bed353aafb1b13c82bbb6aeabeaf99c0ed816cd5766bdb9224f7611565cff27cbbf21e3ecfd8722ba30be09bc3381fb28db1f760bb8990f9e91e9e7eec12a0ce56b224e405065a939ce7ea3f36f0473790d6338e44370f5ae4159b4e6543f3a829f5cb7cc0820806c72cc6cacd5a685a0a077e693d1f9b09a13ca2f2dacd94d32c0fb0cbd34955479b69c3af8a1500ed84cd98a210dcf92913ed2139e2e049b623e0477497cfff5b634baf880721c34792b91d3249391b2ef3da7cf968f70ab4193a7cda318c840a6954c7fbecc313c7bd4b4c48977a6aea5c9ed8eb83a6a3ef6cd4962373986a576d4d5dde9825515b851d1d171f1d4bfdfd70802d8757613fdb0bdea23694068c223418492eef8bc89874b2ad69b2f684b7d647f09e96ca7603afb75d7432394c428e7a5b3643309cb756dd9359b9c5594be8a90174bbc7ba4505233fc9e0878559a7cf89fc2a3c5e3cea39520a746bbf0b8da0083c3a5def558a9cc033c083257e9b96046b4bb22603a9c624b4021e5a03b64cab1f88ea5723d24aa79c0d8d581b2a8250737518fca3a656faf79d5df4e11888ba6992b4d02dfc70041d0cb967697e892d38131b2985412f0488a02c3a58eace7a2887baba19420bac19290f7f6f3482532b1221f8166a3919fa625eab30fee90c771a4d7757513d3c2556946919ebcb6d68a8ddb5b88fac4d622ef9de23add373cfc0c24e0b9423a3c653de3f3159b151cefa04f1e9debeb1188dc6c667efc17423f4f48a026e60474eed3e4f6b2857b231d92301f77659a4e3ce4b5ac09709d8a99cf915d225893ab92a3d6e414bbb626a2e92bbcb669ef023fd1eae849aeb4d675c90bf9fb9f508dea746abb145f45a7ffac77b996fd3e835f3f49ae5e93452d4194c57a2abb78d11be4c340c02136af8a07fb9036e5698027f3c315708e17b8884c5e65389f7b0c7bda650b2a16f5e043da73c7b942b9e3b7bf4d42495eef4f7bf517e3ec6e82ccccff5b093befb9cdbceff75b546be4413d1b8205f9a83cd090faae334f0bf7354d137f8c00dd56b59018aea2be43408f579867203cc0e84110fc436dd209f16f5127464f7835d2acf23ce180c7fd37043e8c283f8f9b228d475d3b1cc5cad20683a1082808f0bf20d65a8b76dc33438c3e07aaecb574183e64d7c4bc8e6cad483612088f32649431e6dad88324a61a23067508b963a8ba66cd3ecab1f3d99f31cc9b99b76fc33430072c2aaa35ff5ace9f6c835d6524bfdef562448f5c71256760f2fe5469f15c8d3896c1fa79f1fbb32dd4cdf1e6da84a67c47ff790289133900641e4f468e8af1502d3d027a5105d9a87492acee0956b98b798ae5e74db7cdee47cfb8d86e812e97acef373029e9b25b09024d4df70e05e39c213472578b3b8c24361bb2b89f91f8a1e06f023ab125a4832239bab93a6b9222ef4bf1d13ab4b2726883bdb6c0c404c82a5895bb6f1b6f5c18e7a5521e59c2e5b9f914945075e41505eaf2623ce1d773ce5b52054df5e91455b97e287d149977d4d884ce9df1d89351159a58a1e8eee53c80b01ff350119337656f334e8d570f5d40f55a632075256cc52b2c3aba3091843ba63a53d2ab622a4d228e9a2d9f471d5bbb9be59d74d8237812754872fe4a1d69598340d5c2c19dc48accf4c75b3e510a3aef51ad4824420ae16ef3cbaa32d429f4e8ecb1f8b84f03022cd3e777e060cf9348b3c4eb3d595b40f5e0f4a5edc79a0be145aa8bb066440badea4f371fddbb539c7c9ed88ef39607093c913d7e2835ff896bedf1c85a1a2a0767ecc5e242fc37ff1e461c936bad015772bc05b51dcbad161209952ae4b832621de9ab118baee0306fe798d579304b9ec6ea501694e50e2a47fa83c0fccc314684ef82cc338a3d84035a93308186f24c05f0c699b07634671ebd319f13e2cb1b6e1f461b0e3af2131578985b0295fe9a1f1909ca3702283cc7f154101e7efd64f3dc7dba5154a1b9a8fdd57fa2d23281b25632aa3f3e3c800a4f51823ddeecd2507e4f4ff4d3d13c4660be1c6afdbab7e1f936bc0d2f3ac2f4e54e2f45a803e2b8671a9edfd07ad1731c033ba02d1270e7a6ef6d0c915bd0aa58725dbe3b0fc73c71e8234ab0b3a6d111468b8f47b3e2c5fc4bb6c53685f96b4498501c15686a796d388db6e2b791e2b3317e5c89c66edb124397b78cdb88d2fa6827d3f60b66e6a2ebdad5f15de7c1f29069f2aeeb9cff5a2cf2c10d1da89f9e89beab11f4f1e1bcdd9dede61731bfa84319f03717c957dd8b39d61ffbad466a4b0e8c525de60e52c5ba0868ae6f88bc6398a94071d20c08ba14d544d069924369b6992315dd9e0011cd2f1a12bf3ae75420c70048da3edd49b5350c785966ddbeceba410136f8c62410bfb317369414047631a5601ebbbe438b903e6ce8419b4d8395db8a9159384c480e63a9e11e397a741b5b2e972676d8664becce8e309d0d28116450b380099879137e166a9d17226419814aa238fb9ed752e1d17df8a39791cfdd7f6cf0ccc53e7dcaabe51e19b729d7cfb8841d637315f79ab84c89652b02c506830c52c3075d1f355a4971709a08e80d23fa3ec6217886135946cf5906e412ff87febdaaf769f73a583cedb19fce132240dd0d3be6eb76d209056e469be7f38539b584fb59dc5f70afbf1b05a457fa3cef64fc121c0ed0757fffb41619d5dc7abc21d149971d8d2d864d40c9afea98116c73521508565333b417fe27fd9e488df9c453fab2228c56f15287c85fe2e04e70cf986bd7c3d28e01a67cf2c1cb46b5bc98ff3b483bfc8e41eeda8767cef9970361bc18d32fa5247d3f587da5677f58edc5ea7f51b1840375f732c97c43f63824c365087a5916f73ddbb6bfec8f2a1f8dbcef34b0a3fa0c56994310227f95a4f9819155566eedc1d37864f84bfabf29d2748afdebbdc905b58ce0ff86aa135a7eb839ea14ef2bb345e6336326a14567dec0e1f845cdcb69e653ce1e228d4d32573f82374b21669f749b8f43e87c3f0864840404b509465d19945413179666ed4adacb95da43bd70a6acf9018dc4c24e08c07ae2ce72795349f0e55989fc1d9ab590532780caed3a4f94384429eb7f91a3491134ae1259bc786576f75753f937a1824014aba3b44d30913cd6f17fb4f9469cbcf3a3d1495d2f0864478b750dd2d6648ed9792e8e4f5a109827bf3a68c33e3dfcf87fcccb92e9397df74bd708845b22df6c5373aa8c133213ae253d530b5de893b3df58264b814a0bf96f7237abe3f567265000868d709e888646e764b3d35ce1d13df63c1fbe7c4ebf809648e07862b22de094d9c91cbcb440fe91aa15d06f1fd9a3d23ad0685c61e5f8fd81dba11d0f3e0a95d0b25e3ffa15649c22079da4164607f55c3705bb4a23fd18a9df272985bc75af902bada3486d4aa4bb9a3ef2b1034cd35314cc129930c7b0cd2993c09e1f2a3520b51c18ae542af0f62c53ecb91c34b5ecb466d6e7151394a85ea809dad27586156bcc1834c2e906ad557a8a6e0c2dd5a4dad7dc01cca83749b224be1e02944c7f1f07f66c2039c020fd9a71346bf333c4c03a918994565324918b2b2898c539852f3895c6b6421dad265331cbc263676dd9d8af98c46eac346bb5b1d661026b7efef69362e7d2605b03df4d48d907183a5ce2a478332173a31e7ef72c7b3a96940da0436717adb0f049f2b3c2c99a85c6d5687c25c7fe3b5916eed48a12f565a3778b15c88feb31fa6cef5dc4661478fed77f68326abf1740c7763268cb6f6131dc378ebe8279f45cffb1b71880199e2802b743f3919564790b3261bf8429d4df0773db0c15f033efe3d8b03ca8e1d196d5e82b0daa5c0410259b8804ad730f5da04cbc003c1e4ac403ad8d498fd01284e7ed1f3dff318b35724311948297fc905c97804be0abf142b2d597c2cc1960cfe2f26226a5d8c4edfaa97c59ee169c4ee4e9a39248cbed804e7ddcd16deb1a8a9f2874f3f69c6b8581839440fb722ec16a167750650d067edee624a26ec8fa3f092ced39ad081f69fd453a592c72fdc72790994a2573c76a298347070a97de253711db295c2de8b3e59c1f9674eac47f299a76433aca8ca38e15f48451ece03f608c594076d5f0d9568ea34d1dae4974ed00b32dfbd0f4b4a49f4c007f0d670ed6872ba8157bf46608691f5450b7ed6f3a4d4e7b25746ad9ce65884a41e93093f2cb93782583ff306136b7e940920165f08ed756cba78b3164899746e9c4eccdd5030876c1c630a5da9f964d41325110bb695a145cfe6342416d1014a86f03963da532f1ab10bb0960cd9e76347d5e39e9e7c581f588062bbe6e92007abe9917cdc606b1906fb44d313eb3397fa10e07193ede283c393d6e16a5e7342d454e1fe1ad0027390ca70b5524662581cdffc4a0b3672ebddd975907fbf75b1e3784f7e74bb626d91610884405205d4cce063358fdc5d6f08ab2026db4a6a313d5f823bf36817fca40fc408be42711996855ef48070833963f904f4e77a3f94047ac7237420f2ad35979aa246e30d2472bfff954cb32e86bfea525a98b80f72490002e1e66785f97521c43f169f5bc14cea644c6457d577b66a4f721c4a03a19643d5d2b03290ac48694119fa64058645dfaa4c0771ad84b1d79bc8c134051972c87caa06bd169094511013e01c7fdb981ac7f5e509032b0a392da99f1e6ae24b586b7b0669ce190c202397ac9063576b36fc006c7b054a23c3b4b586d0f41345dbf663ff5bcc0d9f4019d7b232e29981eebbe0bd59466f5476ab855792efcea47a7da0e0fc8198b3e70cc89f819362cc4e83831b9206f01694ac20bd2fc7b49cd8f15437c3b082d07d9f8202fd78df855e786a3db07f27c8ad45794f3f7b30214cd26ff3c142f614638ce91991576d4054b887ee1e600ec076587fe099e1282a25c2b0f03a99e22c245acce930dc7b5108b0a3f1e406de6aafa51ad9b8880e894e330f35ad15445185ab00b277f65fe8fe8763540b4724cb545d8f329eaa3b2ce76b32f391f29d51317522f0e314797ed7f00c1c710776c0e99b551b2ebd202a73df89190b279642d4008c8beacea81bbf3ef358ecc1303808940b967ce8199ae6635ded7ad94d7712740d57412bcdd94545deeab5462ceb4a2aa3615eb224c68255d68df540df6292b2282ba2a27de924bb323d56598c39a44ff1fdb09065dbe3094275d53e33e225538262f3d4614fcd53367e7a2fed348712757c3074a90079cbd29afbc0b9934fcd78dce137edb542124f0088b79bfa7e245e3a5b1dfe3471459270f57ac26d70a643ed7fb848bfc691fafa880bd8be1049e4f653434fea428a1bddfe59e3ca6f0fd814f551062c91ede61983a6e092f646238c8a6209889ad90a5c5888434c55b095955d9281935cbeca7adab8d56f40d01f429faecc6eff0bac2cc264868c0c177a3faaffb85dd318e996bac609c8185c20cf79e9b7da494359ff1794ffbaf018fa40f40e36e70b161c5626152bff0436240dc4ef7c4f4a49e170ae0a6f8abf687da8f620e77e02ea757073b7dec2365d58d25c75afc7373406677bbfd9e01100e63f604b2049918f8293500a401ea68d1680da88b8c49b9de9554860aaf508f16a27d99d27e6db1d3f0588e66b5a9a2260934f087edac4b8321d77bde15b20da9568617c42ebb118c8304db0e0fee0ab7ae902a7d5e49ca98ff31d1d51f28631397748973d5c9b49c399f2dc58f5b9fe31f11a70eaa17353332294660475b25d44f30c2199cce786755b77cc60d8f2bd7875799143fefd769786c50f7284700f174e8573b2678c8e9caec72c5836e2b183739cf9ec21090a60a43cfa1be4a76bf471f0780ff0777765857063ba4a05e91b1dcad20f6e661c4e4e819834d1e6fb5e580741e31b22cf42493b2ba71a628be19a215cdc3b337df529434679490676d88c784d565c4cdae4899a84fb785393cdd1d05b70376b3042d2f509930b3670023fd01157f59c40bbc63a285b29f1c22de755046eb0f463c964a60c50a4f2b204f63c5d45a6bbcba65775bb91701ea90469cd1c9fb1d41c615909fd36a2988bdd574380e5ea0549e520373879a61e4cbdbed042390edd9a23793f4aa0d2c126c40233d8aba0c8abc3d51d6d4b52fbdc53c5cbd7e3cde80ca725081f621855bc7cde50161c34bdb31f0548448091ff7b48b21f97ff825b92301a2482527a94785a4de140e25b81ea25e023dac486c0e72ee725fa293e9df900c4ed9eae3aa469024fe5d2597c186c724d599976787b2e4bfd9be3338aa30ef710e6c6b811de1f2f53e364f673bec54e4a8fe2290e61e640495f8a984175f0e8e5be3721a1663554bca27c940ca4a1b87e9e7f49426fdbad75585b956cb942ab93df3bee489b29a24aa38699df76ebd553e0228d33833ce0f9330a4d344553da401b97037200a1cb3761b165d2a51ecc2e88c388c86e7cd64a5ed963f208718d0d52753a9acd08618519d739ce3e060ff2aa9d018e23041ef3277a60b4ceaf49ebd2e67128cfbf702cf869f63f9578d6b60de1ba16850851a781ff36801e1026fa154bbecd60853f5f11bef252717b8c4fba1a55311bcdd0f2128a3a0b0ab73154951a20808cbebb65b443f07dbfccd6ce1998d20f2a59d0605a63efb5b8d0e1960a7642597a6a11205ec5f07344c35e7ee138a37b2e8795fd7c19374cdb19d294c564f0151512dfdef23ac62ddd3b436570e4ad614ebb59a2b266fc01a813f9a11ffb859514315e10a54d54c667bf89973c09e4529ff32809de61e8a7484b7eb8b8b0c8676be0c2ebfb8fe27236ccda39a215c5e1aab02dc5920f81e5e32c60cb792e70a030452489f5e5c4a82492380980dd3bdfc79817f30e5de41c42cf55cfc451c4198e39ee8fce66b43d8f2af564c8b6a1977121994231203031ca342578d74eb2a0647f32a8e547e06fbf7accc399bbd2e334c48076efb02bb52c85e207da77494e2d4938d0108cbf15bef898984996957954e1ad6bec745fc741453810f601e404a46e9c8453287863951eec893416be9b07564a45a0cfb5ac3fbdb5c185424e0973fa53bdb092f8509d92e00d8bc85a994b9c06b192b7caee8a25c38b8af947427662fea773c678efad037c82bea91f078ba209944d456d3d2ddd925d7d47ea19b10bc7ac17d99e8f3fe58f96d6421d5f1d942130115859b8401a61eb4c350af70ece773cb86e164ce0c0bfe1882baff45747eb9f842e9b14099c02077cdfc15a104de58927a603e5d37d9d57999c0a09131e15c7ee189094bfe029d45448c2f5dca31d060ac8063b4421a32df1a0f329128bd97981f3ec730e33da757c04b0338ae91c848d1ccf40d515b0b91d3c1bc430236438106716047d5cb5a2e07fd7fde56478a1ea16161c0c752ea09cd264800e9af5eb9a8ff988922971aa363b33ac9153fee65a7d04255d79f4b9b163bc4de1b2772f4f208a4b1aa198907bc7f320653fbe4bc6f154dc0847b7d74abd2a3c873c558d63a27c2336d957094ea97c9ea07b891b5c21b08b4d4ccf4094333c4b6e25e7dea814c26d31c0d7cb4bb11dd4736cc027bc47132e69b53884e1c7622b7d1101bb2471d70592949043820b2a8f26909648b8aaa77bc77cf2d6e7406d817a75d3e9fd7d8df74bb4d7efbc664deffd47c6effad1483259631ea863619fe288228687e4c60495c5292d483234a289e2e29ef5e9914a20c72f5c58bf90560b82c91fc957a22ba622d0101ffa062b114baad808537e842bb88150dc568d6d14b0a6f9a85516f24142c1a137eaffce59e2d3d5f112a578b0ee0c9bcfe7edd804b2ad0350132081b6fe18eeb891158ec913a9805fc9ee82454da8040f24fa3a0e63fa718288b3acb0c88c6f0dc2c634b7da6a27c60384d2aeb9cf904e07f41cc1a1867a3c09e3720dda6d4a33a238e089823420e8a9058e0a3098058898dbe2377129cd01441a95d00833b02e02db959ed533e38b5f7656cb9cb0c884da1e8251e4d549edaa35908dad41467d207f0adce666b22754d5a34507346c9a75f11d0948fd4cae5409fede8692e5f44c0adc03ca940abf1e6068cc47f4eae9c2dc804189bf9932d6002bab17b0e719e72af712d2f227180ce941c795e6b60aee3e8dc79920c16f9fe9c94900ed2ce276b0c93f664fe7fbe47962134ddd01282020b24ab74b173d976e785d5b2a095b74a335f8d24bc86af4283c1ac8f85fa77520ae787769e3263f5dc8175f15d3b56496f06a0a87b93cfe9b0af055ffecf7dd57100dde04cb5c00cfcef86e220de238a37978843698e71cfd0bd9fa5d0489af248caab8b95d6eed111e0e62a5e125842b8d8c34426dcbf68dd0b64afa196279a452695bddbba58edcc42348156a563f139a0cf3b3ec81cf88904752fb2dcc5edf50c65c7a2af75d2af88896116032281a626c599ba8e99849e9a3b8cf5ccf3bd9a1580929fc65e47fefc02bae8cce301ae40ab3b8615502be62e976c8a2eb7cedb8c802bd62eac13d25c4aea4cc7b510564c94e110130603d40595aeac5c730c55bffd11197cd7956a5967b2674e5bff6d5d1f339ef0e1cd6e46249f8d6fad11445b0f134443f14d12947ef4df954185f393046682afc7baab27bf0f4cfe4c5ad9b5e48a300597a45e52e91ce63f17d33c53005afe7a7fc74315b9dee28e4ae6ae73b3197b18a17406195d3b1c330b4c4977ca9c6453b63fe94c6d0ad43a2b627e2b784950d1d34d11db1435d8a2609ebff8c0b6513ba7ca9a86883f32edc88a5da0f549dc9bf648a65e41519152e2298d25cce820a4fc5fbc9c79762519992db72d52270737f02f8af6ddbec572d73702707dca4f52e9736077fe4ea2c0204e4ee041e04b86922c9ee3880dc4e52e9fd0f1c5d22825c77a114f37b645e57fab84da09c29324cff09a37550cd8eb1c7b8248773dd841a383d0decbdba24326baf77bf4d1a657fe334f29af8430bcf787541ba26af1846821e10fd0e785a313e919b5657bfd6a72c9f84b9edb7bb4b1c6faa5d23c2fd1f326e241b5d34237a6b1b51fbd4535f18649dd30d72e06dc87e9f79313178326f347f441796197a2d2360f6eaaf6a7a2611b4f834bab17f5a92666cca566fd40436eee6160efaf50a09dd84a38daad989da0e07fbdbd40ef027235bb4132cc0b21e1fae87e4795bd7d055d6d5f8561afb5a3926cffe17d575184323f6e9bd9f431c99df1cfe3db9f6992c18d4c13fec561913fe2ffa57fe637272a105ef26218d50649cee8750f233b238ba4e8206cc18f8092b0654c3e284cc101b1616cbaeeea519869b44d0dabdb5c15742a31ba72e9eaf1c582825c360b8fa6c5cf0db53051db6269a5636f56e2343b0ae6434e3015428f7d29d6ecdb122e83e81c1f38da095f9fe1734928ddafcbb4b275c78195adb63af113950fa5599f0d7e016b6ac7ecbe15da147e83cd8a77608a3f3c4ac0672d9085778dd336205a5bdddc03a6692a58474f7cc17a771c62f74eee76f9507a7047add13752f1b448e03585592ba6c28637f5199f065d35258deefd92d71e8d00e97bd52c231babca0c296d8a030e0be9ee43ce4ccec5f52e234c161eab06da7fbba76964db2bc97640c357d4b18987e25794b945326105bcb93565b2e3014c810665d49dd5ac65fd92a07009b285577c4d259bb77302cf3584c3b6843b5e69c7ea8195f01436204775544eaaca997ad312e429c35c3870238357c8dbfef0e47d80197c95429188a0f44933cadd68538dc1309e855a4dbd9a6c137a2b4b5dd412a4fd02cb3fbc57f2e689e043e20881152ba9aa575ebaf2c2372542c5fa8aae218c1ff491fd3d9996b7e68c46e6e54ac3c2a66efad58de987fb6f6ba9f0161eeb510d56f29e10d1ea84af07eff47656a80dfee0aacb322d012c1d7f8391283837a08db607e9ee3a2aa2be3f7d0e141ab3ad8b7dccb33b253b702d4bf93d3cb6d721caebba238d7557e646c15102308b49bc2cec8d276c2a3c59727851b08e0fa20c9cbc9599f507378483c24216b5f5437856876e1506aa193eecf4c8660716b26b21010be8ef62d859ecd3c8bc4dc9aa174300303711fcc7f8372a5f2c82af74118508729f600978659caf67b4ce74a6c5fdac1576c008d274efd37d4b6d7d27075430c6d9afd158cd5a6e6d006755367072ccfdcc4cc9ab1a1c9ec566042e85ea72f57ee96ff4579f8ab8d96532de50fad5eebfe9f2bb7ae3564b27b040c209356837d9f75b2815365a081bd807592b89b273ec4332a3e38223f054e24f7aa2274873ef9c4528d2c1d2ac2a332efda38a98fde70309cab099f065015beb400a7bb2138c9e2ee96871fa5b1be2911217bbc645202ad0d3c020bac2b40067129fe15379eaf365a377f05d170f9a439e50091d35cf319ef7c913f76c665e0338c1fe4745721b6b1d17bb557bbb143a36ca010de13e7c77f3efa9b05ff3690b2f56944e26667bdcc12da45256a27a9e615746125e114bd274b4a837ed30eb0dc20c845b70777946753e59ec27db0422562706a71fa88f38868904420383046922eba8b13b72573eb7fd46d15820d011af8169c750ee01af7d1139676be981ec1db42f67072f6ce475d76eabdb79e260306a91ce2b44d98944d5849b7b71c13272a8fe37fc2164e30df6fefb8005f060afc3d2ae665e4379b21bbac196ab54852c569b860e372f9d6f0b428877f9b179a2f4afe2fc31b8a16927bc7b6b7f4fe974b564c33426c0a2aac15279238bd115d6a1d9f38989d1ee3b693dd338be494cc79ce73ac354d5ad4015288cdc78836f747109dd5b9774180cbdbe8395fc7f7afe224d609b8b72caa234ace8be732eb71dff96e7f6991dfd6195c3932f74c570c534ae0a2eef934dfff3db9d91ce0f4d449f759a611eb53444aa3888a0b190fb030fb3b1b955ced086af2e9af3a844bcf228242e5cdd8d4a09ad3bbb93a8ed7e65e33730c1275cd4445926d8172a97537e90fba2e3e3ce99c17111f4ac0ed5608ba4749827c7637576c097b79745afa3289f84ddf5e744bff7d4f2c00cb90d572a2cc25e875ee0b7e22a32dd37edf861dc273abe881ff987330bbdb88d914d3d7ff56be57e21b43d8ebe5a3687001ec7a520a14d020093ced301fb1bc2c816580fd1e969c530cc9fd77942cd3805396272cb8d1f3146b8604ac244172da5f7cd41983346702d52b49346fa69a2d1c6611e54ad2af68e0e8f4c8f42f49eea11019fa63534c7e709c13f2d16255a324e3783f45fc6723e4081b0d63d78e8591d49d33c26c6dab1fa544c677b974567a3a723e11bd6aa89f88aedc1d58459d983d1af9eb0747044f226dbec60e2eeaf72e48baafd328fdf2171d90f25d3339f245f44d16a5a1f67852f974d85da5b74df1c96c8b7558545a8de084a2fcf021174f63a4c4d5a54a48f7ca67ec4d8f88c06c3973d846c1093b2d23b6a159fef8ffb399ee29c212bceaf2c23378421b54aaad06229b278dc9ec011fb56a88c8ae959c1d65e820a1881f9d21253649b7b454fa4f24bccd73238475453d843900403d7877b3d489ee543e52f27b66a96f41c2e0a04b66bc979efa7bbe731316e4da34f26f6c1dc990f7191c809348be3690e0f1eb14cefa3a98df3da2e863ebbaa36d3898c65095c93cb3415e0eec865b9ad5339adf87b152c1669dc90fbaa72aa0ad9eb620eed51b57b19db9015d7d55896b516957e3a61fa3a36280502ddffd79be823c088f5c579de2ce4e76ba5c93d846d92874c0c6ad81e14442665b35327d2792f3d70712633cbbfec9006a5514830229410c4bdc883bf1aab3aa31bdf7bc1036c46007de0454873f64f477484e833ff6d068926db8dfa8ee630be65777a26f9ce4efcba917069163cf53c55d6a8fb05f916209d2544d2cbe590e77e7a932c8b20661ca1ae211b573d4d35e02c3772b72ee4512ab91f72d9932a52eec92d3f15459b439d004922585fbd573acc133721831d7b9320d8411865ac010ac0fb3aef6a3d39c3c7606d663b26ba23c0f32455c39b504d94e8a6036669d807cb67933d637cbc6d157f0e29884201189de521a03ac948ffb14bf0377ace4c1c4f3e085b11a49150587fedb7f76fc454c7ad9b783fdf7212414019d7fa2e5927a6677fcb0e857df2014b84d21d3ff18705b5b4e55ff5df5652ac4fcc06de03eb5960eba688ba36eb01a9daf895ad6746191b8660cf8f20b6b23b93199a22d358c2f2508450d2c304c49c6827398d8a9d0b24a32f0763e4b25ea10241dbbc9e0989eb68fe71dfd1df81322e3c32905cd2638aacc8655e6c571665932295aac61eb2b222e96322b8b142b8bdaf0038b0dcf4374712db8730e12db89b93d29d49e1b8d7f28f7fa41827ea7efbfb44ac8d719f38e5bdc3959491c3ae6fb6ea91b456dd7f859c506784ab0a644778966de81c0f4be7224eb1de63ace376a7a3e3c9d60edb93c2d3f9dab968706f06fa2b9e065ee3295d8d3dc242037973233ec5658a80ce4c023abb6f31df6bda79dad7a7c09e56f563be2a85b21067a0112fd39924149a7fb6fa28a70607dea60f76efe615362309c77c9913baef2f80db7b37146975192eeede2b0ac0eaff346a9d53df0df6c17f24d276b3994c2037896be99a1c4f8e860657d4c07c80c5d926b3ad0dd5ea424874a237c52b51ef2ecb769f4d18dbf4f4ca96e2e062d86ca6da520105aea6df2718817cc159cc7999bab15bb45228d2404f14e5406f91b90d5b13f65ae59e081c0014cdaa61ccd5c53dc73f54384f8747a30ec1c387b980b7558c97560a65ee2f7e720a48d0f875cf5ce067d2cb3675a2c0d6acbc52e0336beaf90e33174605ba59e1a50371b4780bb51ad2f34b146602b87d9fe23ff003507d74fdb35dd5011870265346fc3a0aa83c82c0db3c6e13222cf5985b0a6a8ce80c4f1b4f615a1b2ab262b730d923990848160f29fb2d874ea9c22ec56182c8ea6e9d65f85753497f8a06b367e88d9bb92a064c5679687a35fa1298713b7fd0d273abc29e9f43db765d50c4a8b3056a3d7b22dafd2a4f8f61e3300970215c48a8da0aa5d955cb302d37ec288896ecc17a713e5a4ff0418a57a98528b0af6b32509f7cf63c1c5bcc6ae4f92e417b03d0bf949c05f3fc94a0cfa8eb466774824ae0a31e0ab0650a3a11b33323ca67051ce16ea6093f09dbc301b38002393bcd4b5fb2800ed1598194e6c094cb59ef54869150608fc08f1197099b67cfde4b450e49462c9aa9e2c41cf357acc7d9e444e23f3419af261fd6b3565fa9ae08e16d70d54f98500750a0d7bdff2d997f1c3ab42553ba37cb93eea2fcef6e0935b0dcbc8d1ff4d112020a5fcae69734963006ba9f1d4d3ad2d5aba268d551c760b1d87e2f3c57b582c552fc8db93922f46ecee20883fe1a5b5be3bbc9983bd0eb0037ed77660a85ffb1dcf1f8dfeeb2690490dcb9a7be272e5dc19240b25dad4046ac9f45f53961abb663beb67a2c58fba2fdf60a56b7b810cdbcb1dbcedf72107cdd5305b1bf8b0db4118367175d270a15971b2a973b9db0ed7ab18ffe0625ffe1c8ab84540f6b921fc11c4b32eabad89a096f7faf1e347cbbb8f5026b2c021d6b62343c1c9859ae7fee1bcb6c870bfb4fd98cf0adb5aac579f7a3325f344a0db597a3c5c7f2eeeb99d86081f61c28c7370e7c0a8f1f350ee9d6cc3a8dc764dc0d92e0bd65bd43c78c6a148bef2bb90da966d9f78d5136311912c3d541bba25fd66c5fd8f804ce728fc900024986d869d514e3aeaeb6e017c8fbd47d1d7fb1c144fef007a25fccc1f3fd4278400142580751cab9ab66bf38db87d4894e97d45bd75e8f4a01af4222e03369a921b8d9c606cb8ffab4ea387ba82f5f3f6ccd6652a5f928a8167944620615f41e92f3a9fa20fa8344e362d8a04d041a7fa1333b4c54ae213ef5dd224075ee0da8d95a56d148df872967493964e7d0e37cbb8d79721d8e252f389c6c90ac972c30b15c657c4ac8e769c7a5d18963130d6d75584ab9c9153bb3fee1eec925a1e3cf5ac7114c6a347db77baffe1f220f8ba53472c34861caee14e9c811908772c0f30e266396ac51b5dc8511acc872ac3e1d314ed933d724c8ab5ad274ac3f4b173b5f2d78316c32113b72c164eb46bbad85730d9e2efcabf63572b7193c024ef7f00879cee57b9e90782e349e720df916f691e0f9fd41d74e3175b8c4d7e0d863805b7e648e911277ced809c0321f16e9953486862049214ec37c0c756487e9498b42544cb1cce893b3485a3d02ae6172589efb94d26739dbf2a30d0ba9110070c7dc19ef2318bfaa64d151aa2481febea424f65f070deb9161d8af6a9616a367dde57dfe4d167eee3d133751d8895d71f09273776ef5f759191bd695666761e919f7e15dacbb75729cc83e380b5c2e98b222536072f942be3aea1550cbfb6601db1ce6fbab40919884f982a8a08020d411ba0cd06bb21f4c1ea7a4b279399b13ed4498cd2b69dea9136ab2c240a2ca8555c12b1ba6b97c29181b178850af1c7d6c2f2a92ae92ddda6d64b2e9b9481e1803de6bee30ecf265036ced7aeb839ab9ae56018459316644f752920ffec76867a2de13b9fe4f0fb07002c136d1f401793d20645b62202e1f323148b5b308db808dae7dd3877d3fc534aab885cd7a7473d027db08337078bd0cb208c6548eb3b365a8dedd84239a74796a4f5b96db1cc3018babe8ed6bc4fcb7830c785d4bc2a623633fab94c34d3cfd4a7f2255171ec87511169b7d15d1b6beb98856029fcf6de9a4de02da5e859644018097ac219c124eeb7fc31b9a97d35b962292679ee12a31cccb790a3c00bf44a2fb187d76847fbe714053e0298d3d4042faf2964ae93b75284b6f460260bf6cab788cf7c19f2becf723a37e0d407f01264226dc0c760998ff868ddfda1d2507aaf1baac6e36355b0fffa1e02dd7b11173b4d872ab5bd79012ea515ca8180150da510c102c3bb06b0ba1e44ef15ebacf6c0e457a3ff21f111f2ffc4da5e23703a3ee8dff2063073fe0d370d48b453b364c698c594475e0756ee90955120d5a57a609b9f291f2f4a0ee5a3b1909278d30555de621ce5a37e2fba8a1d39e4c6ad6d7186ee2eb767f2d24b396cbb6a302c991ca81f9b8dcdf87d9ce2771b9ad641d765c1f0f59d6840d24e8b8fc977c7f047ae7ee0030926e9a549e4841ff7cc7f24bca025738a200e2d03207fe3129e78829fbe51d4f2dc5f340cc9d47cc23ccfe42267ebfe4b2291e7defe7a200f30f318cec9c46fea748036b859d215d78aa76332cfeefb39bb3e1dfb71f0918a0e97faacac015e4e6b8da27037a5759ab6cbb2df4a1076d2b5e157511db195341ab3d48b5d62654f415c1d5621c474bc5a14bd9c92f634674f6b420ab14b775e284589b6fd54b64d7fa4d8d3006460496367de5a276abce4ffce22ab58cbb0d5e6d9bb26786ec6131c6a2edee447d1fe7a97f161e05156b5f4e81153a13e9a790e68cba766b01e326a4f4f6afc5d608ade645f12774bb1e0fa7fec20e1e56853ba3613cd550ff5b61174e06a3cb539dbdb06a329ee6649fca990a67189c7215d83f2a790df9b4e4e30262c52ba65d7d64fbce6596cb5a563bc45cf5aa7550a9e6d09738827a2a65173d30abcba79dcfee322a02722781ae1518f215fb10d0dbc9c3e7aa7c022da1495f24ec56c50adb2d16acaf45fe2948289fafaa4a20c380f07eb92da477e3ef7d0a0b7eef90fdcf7c721a4afe11d16642d16315ae94646675946767dcf7ebca2031bb8bfd0dfc3b884f9ab8e497b5682dbeaa75a4a61bfa93353c0b9e1ce16c33614625b29d3f60be53654d00400f036e085f45275964d120cfa69ff167a6b7000100c86d795822fb0272081f90afe0af4bbad756f9b91ddb2af66076902bca9ffb5cf05b394a52a93335935192721a81baa9bc53aa6eb5e2e44140c495ec6b620a28a2cb437c4c5a4a7393ea82f5c72245d08e7e20963bcd6fcc655324e65820781d4725efae89c0326487079dc47fd3eaa5db1f9aae88cd267a2c74438ea9df518428d0c0135d95c20f134c445a46eeeabfe71e5545dc8b5a132de94c55d9473dde2f33cb682a4837cbce3ba8d1a6d4ab3b9183dd92ed6451dd015408fc80fcdd93c2e10703583fe424cf3c3f7123c463b25abbf891d91d1066058e538fe1d30a62e431263960c071963e1aca694dedf4d337798855479b38568f0e6b37fdbbc88ed9d67af61471d01ebd06074e4ca0560aa48de4757e232039e270ad46e6d8b81a9180453a2af592064a59c10d4340e42dfd87ca0523c4bf1e074438c372ddb7c510d7f72fd6d184975d8f70878fc4710ce802e3ccbfdabec2071627cf1d3cbb589417cc89b06b5a9e8cc86989409780714b08a07a54d46b5d652bfa853f6fc47f1054c9f2aa5df1997cb5d71aad7268e7331c0ccf4daff06c232cd95b79ab2e02893ffc14910af7c00c479438ec335858c8a113079cf61164ec8c9d8456e84e155f903421f1a201cb48cf8365a945c531e3d09d26c55875ffe00fddcd8c60e69848d9abfca8041a585a6c3441d7c3f61a8f74f139a2d01744a9bc46a6484784d5d5454acfd55eae086c332daec2c29b740f7c57a7ab54f70450dd57a38b441aed5e07bc29fda4e900e0089057ed3b958aff47f10871d50d2f29b8681055b02c3f4f171493345528089a3b79cbe20605ec6b2d0e358a9e301573d7196b148e43ccceeb7138a46897179ab979b6f00e57b69680836262ddc0d293741b6a088c43adc8f111992c1322082f56fda144038851665c4710342e8ee8c2caccb09d72542ba3f983c5aa9a4fc25288a4139573fcff7590d54b66b8205662520e9a9098b6ed34b324193098d23679339053755fc5d16fb04e42834adee2de84c927c21272f72961b7cca4e9e27a794a609fa45ee789c397bfba5ce0f5817dfad7e91fd02089b4f30a9d5a90138d393518be943623fc26cb9e98a515a301079a0aa3c3247743072d3b6e451cad5f45e576002b11196654a13f33e0c81fbdf6b9de6d18710fbddb129e4df6926551b2d2cc28865ba31c6ca2eba3ccb00231f307fefbdb356f426a5b9812d4d70285cdfd0cc614b2b321dab10573bc0c7d167fb83e0a636e7e19284430d14bab83ace4b88e6ebee9193248e25f417f67d0823a73182b569a1006167d369767ca7edb1cc6e7db069c2486891472216bbc3dd0f84e48f88bc5dbd850912a2ecb1a14f6682b69ac1e3583f78a843f97d9f14845ceeac293aa50ff947d657d6d332451e4bc48a42cbf143e8d15dd12d122e0d9f2ae7f160e84b25b4e3d5675f46623c142d3894dabc4272ed1222b704e1d41d3a49be3bbaeb6c6440fc39d287d95cfe4dea5a9ed7b93e86a7e710b7fc2e885099216aa72a851a305b8b18260497e57415340335771d7905f82ee5ee780b41d183adae00db087e85889df39e88a4c5d97cb5bf72cfa349768d94a4c9d179b8cbf43d5ecff66f97e7604a127467e0afa3008a83afc689dd3f035f0010c8ca08fc4d089016dc8ee1042e73022842e470973623789b009690ed5da2526d3316428fa620634ade52927c3a902565dbee7a1b987b02938e6904b44fdd65dde331a6a6c4b251c7887c5eb7a709a4376477f23dfbf42a127e357506f8eac25df2845d060db518cf369d38c2523f63a301a628781b408382f6cabd06384af32fd471db7e7d40da5e3bd46be29c118df780e5744d923fc7e1c3977c866536f593954f5b163d29a82fd1372c02fe09c8ecd758343b586a367f56b5dd818610f7add480e3e438db12084baa32b4db725616b00a01038eee3b717270da27cfd3ed01961374d82e0e71ecd589f36117fb8fa5625c247de9bf55ec3708e0ca3670e6983afb219ebcdc4ffec7e4beef0325f499ee79f18d991d41aa8cca35110829da141dbdc26901a1fe24c8f10da78b682683e17ee7fdd774bd5d878b444aebd4a569aa5e53a8b395855969a2945ec53080fa7e77ecb15f851b97c2fc61d8ae17eba1cc0e3d4408dbb40160068cd4d05fcda94a653a9bbc070c1860c548ff022c896a9d6b0455138448a03825e4ca23d429befc491a1eaff85ed88ea566cceb6405bf6dc4b4353f46e72c4d51e656fd48c1536c0c323293113a9aec1b73d6afe9498fd05105db88f0dd93fb73a86b58d3410f871a8edb0eb24d2c4cad26aac6864761193463d373da930598cbd64d32b308cebcec23f765eae6bb04fa11858919d92ffad76dd0f1af670f0e1d234a2032df919b252735c2b3dfc7acbb01bd748a31adfa535009ceeff725f95bd30e1b7d86cf67e871c970dd94b913de1b3f2b9eef6a7ba7ebc3dff9db5bd9cf8f27d8720bcf460528eb75efbcea50cb2907928af11fa5d222f041af974ffe70833060e3e4c52ad86387c0112015d27bbe8859c2e73d863cd201a882833bac4d838ba6ee10d36d206d353fb2d68193c16766a95a1d11b28db0ac29c13ba365410b6c22139513b5ce544619c3e2d8846faaf6633322b0b4a856854496b1e98d60c772a2064898b39cc49e4979fb29cc1011df54e6fdd6bae421c87510412db344459017d6cc05779242e0112fd56339f2404e445965a570eec66ca3efe9aa4a604cb2bb9ba3250416081d5b3b9780e5e02403c4fd1dcaa78fbec917ca96d7a5609f9198bf3b7947200bdf17d6d52d0d3080bef175c2a8ba98d1a48079f276c472b91631e9590de84afb5ed16d094d290b17cc9034a8aa9f251f75c09c0f9a5ccc198981e0f0803b892f2e2951139788177044be8cfc8b41f8a7d787cd5a6ab2270f810aaa566d25414c1117c2642d3e28b0b0dbfe3a0d77602a67810759823db93dd371bb838be3dcb11ca7cf99381be8b643c5a01f7413b03ffcd528a84b5d823343d5cdf257fa47ff0359e18220c7f201250e354d31b2a27a098be2ac590fea7b9ca5888e9f7f3ad6f888d2709490840006b8ea340ab6178c0491d4f5e4e7191e587b4c82e35e3afde42829a80f73e8e205c55f3d17720977228908f3c057e457ad182ea7dd3fa0fac81e8f19c2cc695a8381e6eb436b96e29aa0cd62663530cf137e480da5b557b0a1c2385f134bf1ff21a32f3c86605421dd6c92d652f80a4c20c1e1c828e179b3a15c94ae428ddf2620b6f998e653f76135b06c5493802b9bd87b9265dd2982283c2dbbc81cbb983c81fbbfb632ccdf3cfe275e1f505e83de3e653bc6bb46bc51b7068154f299ecf45f7297080eec367b98dfcccee76e3eeaa90e946b291b7f923ac04d36da44a7312ea02354e59ac9d3cfe99fefa17b4044388a250a74ce857638002d923f83623761acab3ed3cf0b90925303531fb5273e5251c046c5af7086b8b9edb473369d4b8dd5f2d0736cff2abeeb2e09291f44ac4db357e30985239ac4f538bb1e8650d4b4906a0534985433710e7bc2828b8331a3fd9f88e98f8e13c768cd82fe7fe39e60540f001951b37c402b4503ea8f6670c4aa112859ff13d3ef5f3c948553b14daf4842a7b7ea35540ba51c8a47b266e4f603ba2128929dc20d32aa7f9d45d476ca0657703e08ae0f963e7df497f524964b97d1c567b65487e2e73f1092315875148184493ea91955971a99bf3970632650a14f9b6237972157306bd7a76fb4e94e3d4e3a969a0a8b39c67de68bb0909b08899e4b04a98d178e70f4060d2c65004f599a93571d20d0552fa163c326619cddd7dd7bbfa87e7230d67885b3bec1d652b49155962eff061b9e9964f61185ef2c5ca6245f38a59fa370304b2859f7c91d46bdc3b95bf76520e78200cb23187fa1223c9b076957bc67d2c988bf4b6f3eaf204aafc7cc8ae8977759f1d6a24cb659eb6823c816b60eea279f354d4d5043c7226b4c05a99da831c764e65d518dd003df5429f48f02cf652ce3c962b082175d85c61ca8c29a53ae524c4b2efc4bb99d9458ebba5b1c8b5c9b3a4de075a8c6cf72cf53eaddeeb61c35d97c103dbfe6b58def477c56444628678101cfbcdf61385dab4b75cc59fb554e888d28d025edcde0258753bc185021a99e44c61deb7524975496573819784a7488296abe20b70d3c65dd336a59fea5d990987e7c2ceead782a3a2812393fae2ec0f4bf1f74c12374d1cec5855dc3f649d42e0195558f544e1cdc43376bc414d8dea9004a587177d567d18b29a79c95751985b4c30d53f5147076cbac5659e35bbcf0998330739d4641b0763d4b7f03b371770fa147a54e8c5defb6cb409d5b9e9b41ba4fa593cf3f14527b3d53cbe7891cd775ab70e8d5d02de0719ca82bf7115d206b40ff86a55e8cb555b515dbf37c4c3c1afeda8c3b0bc1078a3f75ee856fe705e72166ec3688b618d0583c8b9d595882ded46b355ee540e85620cd959c04c6df7b2c166f00e9f9248a3ae65f2132db68b9f92762c47121dcb324576dc66dc1d9fd4946078fe071e6c21461fc4db958d4413c23c039ceb3d7d0969a65e09efc6822b63241e00135096470a68b02171652f58b3a6954bd26de689c03b21c800fe6749a67b4b93bf92d10a6285a28994573223422579d0a4dd38276c0ffe8facc287c26883709642c0db5abf56a52c28f351f033c495417a42376d8e9ac7c4fc34087d5760ac50ad9cfeff4df5fb403ec8398aeb830d45e7c4ed6e643212bae5a478c179fb516cce4d1b0c3cd1926ac130e55429b0fdafa9437187ce718e5d7b24740e64b772a997b4012edbcb8d9b3b45825d9df011ab8a451805f81fd28513d6510e1ea111c2f02353c110a23f887f990346cd03904468dfa0d3ecc0d4a05e6c09d3222db5070963ec97943de90fb66be8777fb82a337b77ecd14d4f0d66a43781174bc6fa489c3ba2e1169cafa0b77c2c1cbd1510d1d6e0204fb25de6a8d85ddd975417382860cb33d633be26057cf77617a7832da3b5f0b5961e8d21a739e8ad7a58c3286249cfa0132e552c17fddeba29177d068a6a4c465a06510e03b4e98b96fcf472401fe2677545dcb1c2df4fb79d6033fe632232b42f937c275a5abdb21dc9f7da0fcefd744d6f8c0d592b706869bcbf8962b2e436e805e60f8738ff680ad208ec8368340fd6d6df9e02e0b3e7de1acfe88a8129dbb120a19c7d6b3a77fbaaf98533937ce63e64e03ed022102d6f304966fce5607dcb9d92259d78ad8b8842a53f3a3871fae4fffa5b585f40c83f038084b0768d7da819708268d12101e0b5ce1538911d5cc49826c3d6031a9a17a1a60761d836756571f05cf32dee1f0cc5f799ac390fd65a70ae5e346508abd80a625fc7aad1d1bd6e21ff29890a287c51e2852b9dcee5ef6eea68cdb1d246e0a0b5486b9195bf7b205c0b15707bc613a86f6065d93eb73979d72525552b003d17fc5d24de5d4cb6df64f2066b9891bc79470dbfad6dc6e30be7499f4dbcaf3b9052b38c0f5eb85a384e1a03753d09f31a21179615de0cf5f5db1d304fdbcb44c8b35b76dcea64ae9180c13d0d6f516be14f3f6f99ed3ee05f4914367289505e7481c4989ba738f6f3d07ace11ea5f2fe209a83b8dcf23d9a0b909d73c8f8ad284c315f37c778cedc34f7161de35ac3e326c3b67ab2c205ca7aedce031c251cd8c51347f96438fd19956618ca1b08c597cacb98aef61d9837f9c9a94421bb603b60b5464df348d3d1cd846953906b2f5ea2248c1b873fbc60e5b50a92a486bf18deb35bde2283b23179165a058c871dc69427032c47eac6f29079939f8eb35150027134fbce3bf8098076fdb869829b614844f34ab8a2ec54a472fc348b4eb33271e8fe75a8b9b010339e9eb853a4cfa30952d17ad79b326029d38ba379d9745821b93200bc1004880157fdad08a46c2ac3366290d94754d4bb5c1894319789f1aab8169f3f301b3032c173803164e0154961cf9ab76f1273e6689d9166edf410381b9271638ad71baedad45ab0c524ce6dc8fdb7a7a9c9393c85a42cb6712ec9cb48577b720f86516e236d33661e6a6401d08a80100978e6d3e1e35eed3be199bde95d25e0c0bbf2ba874cef34a241ac41cb67904b77189b10e19db3936bec37ac8915ef5b178ba12eec5366d3687eed7052265ddf3286eb3693c23d7fdfd90b4ddf337b76ef746634877818a9139e4e5f7e157d837ac9dcbca70b3944474e9c07bd7678b411831a4398da9c985d3384177c8df565a2f3bad2573ba46185d9736cd6365a93cf8ab4927141415f4d95db79374ccd7cd0b583eaefe047ac7988c62003dcfd91f2530515a67def100b529ad4263daf73c1381af0ffae315dba7d6fcb6f949766d8150c3fb60caa769b308d31d987738011fb44b702869ed4b2e2d1190c9072194f03b621f8e3325768bef5fe5ed2cb6c6b16fd5ace313fd7f0df7d74e4c66c32650efc117274c0b48ab4c010c41c5daa56e50d9823ad261ca540fd083ba9439b14938b2c4ad9de776c74f2071fad7e8eafa8af5afde52f346b2e72c5bfac1f823fcc338eb077f41894883e3115ce34c8266b2c95c436094f17ba8f67588ff97c1810d01bc3f706016abf2170a065453103bbd2bf061eea058b1d212ed25404a47e74f2ed48ae1c1f822db700fa0b4bafcf46623f1dc0ffc81bac54b2f6684df0b4b40265683424801a23889c006edaccdbd5b8bf8cf969a9cb64b32e215bbd30b4dd132297b08e4c4b19fbc621c2519971d71738a903a89a94db3ab9db986f6d80d33ba1fa21556e006fad2c6399998b436b056f230893a52d9f0d538a1d5e5c2e71bb1b1188658ac173197c98ed84e8cc82643d28719de648399b4f38ed60c2e32d469f40d0cd72c446ad13ae22ea0464e630c87a2c240625307b0e6b5f99fcddfda5f5a9d2114604641bd17226070bd0ff2f54733c2dd3aadf85a377b08a7ea8f838c39415677a4c4ea8d9c4d85cdb2d5de09e6df93da9c812b0f03852dd229ebf5220551c94888a635b9c636f10c56370cebfbca42280792238ca009e06e4a3488f318e531fbaabc889c9507602c71fb0d3ab1043bad9f3f3fe010395ba912d6ef3188ee186f8cd1ecdd2bd66f9ddd8585bd3e0bc24b2ef30403cfdcb8ece12dd608c3274dc9bdced119959daac4260b0762d7fd1f9873317ecf1254fe639b68eacf14d778621aad19f60cf6de3af2ad0aa92de0509a00eb1f69beb00e98acd62c3010f2f21e08c542949ebac783d49ac90cc178a013575b722f326966ab48b16d66555e891de79d02d88bef4febb748056865c6f9155ed59c07b8fc2c733f5341c0a5148c06754ef7e34ae019d6449a554c74f36cb46502a9e51caa6b059ed36598e36fa661aacdee0c200435e19fe16b948afb397f31ebe1caeb53122a5ad8db55b1b36de7baba378e3f3b80de71d3abcc809051796612d9e0fc671c5500651aeb39aa031bdad5f570b566f070f38bb072d1ce4bcc08b061bc22c81b1c7f757a33c8119474c0db5d24f807ec41882f257192b6a68b43389e7e089a52ac4125c7150e1c71ae450badb90f837def0efa458fdcf6e1acb19709a469fa6de047c07e46b43069f50023c18c2d05d8f131699a7727176b0ed8adfbc3e46dd20b89c197efd27be068d96086950af627074a4eee0a847c4783d65d4ff3b87d8048f2074be2b1b315e3f813891ac131853151603837980b821f30929fad8be80fba3d7f5e0860bf530360a7d2e3f04c99c29f3335a11b23cdbccc477f242f6d317169729958d4d028c9bc998e48e40eb0a860fd93b8d6f5fa7972f08762669f2d1406177827f1d0cb232f489701fca9e52e465f0038effe73764f7714b2f0530edbd7dc9f65cf45bd43225aeec74654324ad2642d8fa1f56dd690fe0075450c9db7e740f6918e7df1bee6d66db103a6e888ba6f3643ecf58174fe47ee267eee9404778e1b6aa8af3553465f2f99915f35068c3f6e2b83864c7cbb3d2f398d510b5b0999374c944afcb27d209e6a13b2a0b48df38e2d4d6150216bcd9b1b2bbd85dc4124af0a858dd84819760285a094ed78c756794adf26d49903bfbff4e725ac3c3a4c7fc34fcf46b12dc161c34e1251465bfaa970d01d9c34c7da027b105e560000cfbc14710c70e56f1a10e183a0a4c12dfb6bd067f5c3ad33dcf136a8876ce21e942fefa2692be86eb754aa2d2d0291079aadb4aad61f0309ce3c71411f5f535b16909ba972a087a76552d118d91201086f99a71c8f64c96f43f85691fca07900e87ae87cb673f86fd10e619f6dbb5b94f4f33abc3887010acfbb2c180af6880e8ca1a204c9d731b194cdcaadbdee3dd2a5a8813eebddc4a486b6d555a6014405b7d0733f9d267f598325f0879ab28cb3789a9bfb995a09d4e7c83d23bfcab6e3eef44a0f22f593f16579b85741bb980fbb50cc057287f4f320d12f6b8c1701afcc859bfa15fabb378efee2f11f15036da570c47262272ee35e32e66ea1a0aee3b002f75328b7314619463223215266f7ca10c631d55ef49ce9086a253139785b5a1324b3ef735dbac828bd87a1053feca8dcbe1ba1c8352cc0df6edc2977dd98006841d2fe1df3494c0c0f9d29c98e1183640b71cedbcf1e30c83fecdb39275c585335708dbcc602edffec5290f143fc11990de7528e470927c3de9a82b9d423f238312a33f1c47125e1c4cc7d31c4e38173d1e4a0107cfa016aa4d7c93429ed443c81b6540b969c5b62a4c70fe31abc51825c8d6dbe8dc0ed032c1da5a1b98e2c47886aae00993fbfa2c0de580875501c2aa344435fe904479846065d385afeedd25be02d999afa0fa29b9d685d97dadeef76410c897f680826eb81c00a91e24e4ce05f52d8b22c53ddb2156cedc17d1a1533067732789dc0869905ce0c4fcbbed66620b4544cee03c79114335baf2af8836d46fba990dfadc639b94d9446623537b662f8e570679c2131b3872a0d043e21d6d0cca2d07535262ecd9b6173f623ce5959353c187e8bd1a2d1863feb11b01d27bbf213fd17e0d93161ccbdd6d29dbfc530be9e1549b0474ed918323e1665bada51c659fda084c8e11adb98c9445bd91b0caad5975359a79d42946e0ca3b9a5951a363e02f4f8043a1ecabe2e9c491daf5ba89c6c19e945bc1fb0f9a3dbe7b12740ce41ec1e4314218004d95693bacb03d862c130e9fbd7bf0c3eb2b5f60a92d87b8103a58342e0f37b4e70965353448362703fc78633d33ac307ef5d8c1599d6f17a65c572b8b83473934d8d3f2f902995d031370c85dffd3663085553b8090444347024cbed7b4e3a8615775d969a2fb3d2021472ea4030bd44c0fca083b71ef28a7a8f9dce7e05e83d3ce7c53a4dd0d5e86af801e26b6bf1cde595491708416233a4c04fd60d2a9466f00d3a9671e794e93146ec451448c4882b912195be6d1d8da465a4a54a300bb54866931982aedac559273883ec3855100f7a617b3bec2e72ddffb01f656c71b84c2dcfd38f5f619981dd38acaf004d86e4360c3a275957c467543d8c6686b7e6fea623b7c8c524c9f390bf9f7b4fd7b7949381c64d4ad72e6729f0b101d1d93d5cd2b6040a32b38946d78f1c53f246771a4d116b0899534333af23b947ff6dd7b231b43c7eb08b7eea2013ccc054ec9d707bb55f89c2761e65f12b7e5fbd85bd0342d663b37cef468226ec8053a5cd2af40b9812f3ceeaf4c974df87ce82d84fe52cea3b116d2463edbeedb91091d493a79a29bed845fd6efb0c81cdcd0db1336f7c379ad702f89572ce3f2fc461ed9af7d2058afb74b1613327c144e716de9a0728446804eec789b53e37f707f80cd775eee4e08d674e0d598aa8cb26ff9fb20b61de3957250e3111fb687234f8f29331c46b189504f189f67ca13c96ecaad29188bf8fe6d8bd2acd1d8e89e845cdfec8b7b3969f0a8f53b93d5a57f363c0668c5e8e05d2149ce84fcaff8a815002232a6663221b27d0afcbb257ba423ca9bfedd5608e83eeefbaea15622b920c030cb368f07569bb282dd084f853412a1dda26bb865043aaffe668230056ed6874c479a4d44dc8b67e1019383abf33a8e9db4c17635fbe8c2f5fc8d365a6c6ba6272b6b88b60aaf0d20aba65713bf766a94db94f6e85ce30e6b0f90d6f8132c6e174c38570496733e46f2296f12f59b84ee1be09f58f97b22b48382a6936cccf3622ec51600fa7fc1ad04765f208a5de2896f65beb765734cbe6ac28f63ddee9ef2e31979dbd65622f50b8a1bd8ecf9af6ed25e6ef68b47f34c3a8eb112b3f9c50156c975a2fbf0cb91bdf56d572eac4be304a7e96721f5a96760d119eaf8db9fc6a6ec92033099d331610810b7486e6920c5c258fb1562ee17d12c59541aa7ebb541dd44a49da332ba1c1f08b0e7baa7f78416b53c98a16307406f88e8832aae90e3fdaf39eb1e6513e7ff1f29cc2289542526ccecd3988ca4b00fe29c5c9edcaf3fbdfbee257b6ecbecaa20a928aa008b27ca43a9161b726b5a7d719c7b1b676cecb309550cb53d36a6c3086534040ad4af095c20f83cf1614534c1ab07176a03fd7a538c479d93d25218ac4187b504f87fb7ff8d2cf18b0523f011312949869361b0d33e9c5f8130bbbca5891e1e7a6c3867730d8c74896344632f081fb916f19c0747bb02c83acedb11f285446775761dd7021c7a1677d49041372ee9e363a54e2f9402e0c83ce08d88ef9c7e83e6aad43c42c52cdaa73dca5e9217e247eda2ff38ac2c741b1f6dfc4241fdca7c8771b622a35b618bc9307578de47aea427a691ac014fab0f4bf77c1e824fb42bd5ac56a6b4bcfa085f8898c66192aae34bcc02001278de9d4d1057eac9962faf0fb2ea25259694d09e08eac8f22061a8117ec2e54a1183f261ec2f767829bfa846fc1ab857d7c5b22fa1c0a9106670ea0b0f5a41569e230dc2d5472b01556d6046b05c6deb7012be2e9b015fdd72de75981cd82fa6a931e88a5d7d216d1971065b3be954bdb5f9e6bb619e93c9bcc0f9fb65371c553b016827165c658f30c4858c70720073c50aba585eaf0a381bc985858171daec4b2e07a71749991b86e3712ba340cf64dd3508d0d44bb3f1f785d814e74d57de118d28bb743c53cd553b0918fc3dd5b1a1fdd7e2eebfb58c5bd0ad5991429f08ca600b6a859a41d2112a1c86705400368c29662f2048e49d3464e136d4953cbd99fba61ee3b30a0d088d996dd456d2178716cb04ef016f326baac279603e4aee2f16b0ef12ed3e4417aa40f6c3644e1651fca672a94a3a68d65738102907a1b9b9e3284246160a2d7a78b09fe66f56fbe1954a87b9c96fec8cff729c8a0a6580b67565ded0c1b1610742d69bc4ab44311f84639e55fa040ba61ca31f8aeab8d07f951ab49573e3a51cfd63abb9e052c2ebd8231485f5b6a144d0f8dbde077066dbd9488078b62a8bfdb75d779e35e4c8bad960807437e9b0a551ff9b2d72df3b9d1cf9d58d677aa1ba4c55625a5d3bc8475a97a7e6fa76a305dfef71f750c8639dc8f2b4e04295447910340e25859de895205de9c2234d8a40202a24e22c00c6786ecc70ef47585bd05beeebd14896ff450bd703a0212b40a96d3075a2a28216d58eb98426febf2d718aff38e3127030ab9adf9fb5454d7f252b9bde582d6c48f9e906815b542a99904393da2425144d8907e5920f3d25f0567984ab63f14adbd72a7e9eb687c4b2b77236070cf3b9b2df492d5052bfd5978e50b4610426a550e7084e07881e04a0793931de39c26264cd166bedab20cefdb0e09b2db30d0b8b475d304c34637f70eb7485f0e18caeae1a208923aca606fccfe9a2169778634e26f6fd127075c8eba45d86946f94cfe8da145e4f3a1bf065717f52d5635422ee15a2c86060792a42297996768b0ac5311eba24f43871912257a58886d7032849b337fb23a88b15b846eeff43bfa5240bc9a611c6ae51e903fe4e70ee23c23fa5cabb55cbef410ed6b5eb6ec291c911013ec8e01549b1f8777ffff76e4f1f44f298a8cfc676ce7743afa6e394c83e3e05be7f9c95044590b1f671107cc22142548d7377683b2a3aca15c2828d7a13b1d639bf60d1421753015c2946f67bae47fbe235f167760af7c5fc1fe37db79aba58a99f3b664746c5e141f2a1eaede7967649f4dca7ee887df2bfdf4f453d78c1ccc29faf71c7e366f2bed740bf113ca521f7ad0298c5b576c47421e8630c039dbe2995c9e7f041ea275b23669c08b4a945740aa163eacf3a1fd40ff038f964ea327bed16b615d5485520105863d5c442b111d51955e885e5126ca1abdde748262c1ac032dfcc1a1c6ed672e8170c5e91ce019fbd0a285886d53d47736ce414e22d675464514beabfe0ad84a31985a9a67c0e4e4243ee8d2fe3974a9cec6d1f31d2dcb0f73ed9902539904d1860495d8872f052d081a771862bc5962027b280b58516483c6f1d4bcbc89659acefa769e034e444586c0864a3bb1e13af1615976b75e4dde508635313a1b69ab8335a57942d67160ab33ebe4e86f81b27ee32e0822e90a9192bf982454a3cee5bf0ddb3f15290e0b030e0f381161c489d00959ec83a3e9e88d4d4b485a429c9a793ca1acdbaf61e15bd416e32314c5f96e4a283398b050726f34d80c4e20215bd1253d9096c46dc7deb790eb74374cf17e1e13a527ff1efcdf864b9920ac7aa767d8e1fa6384a4dec588a55bb6304951303ea5e8b714edd56cccbdd12bc4351c76c48b3185f4c2f8c2c868e723e242722d8f4bd84532f463f77227bd057e09cfa94a37b8174872f4086795839985de2426fda629aa4a1f16d4d37f5b3512700c8ed65dbd3a4021d8aa944c9cd31634d994d9d450e0a274dced341499e2ad1f3058d810ae34ca2d315cf94f3a9f879ad0757341c23de6edd0e97d741bff18aafc32236153492f6be332f1767d8d0326f4b3b86b100975e37cded38a9f2981b93e772164197e9da91a19b249098258668a52158ae761f2f469c1cc2ff2f3e848897d33e786895cc2a56ea6dea75b2ad40bd774f9bc660c18681f95aaa204226c5c44443c16c6bae6f480cd8941cc39a4c39e31f330b1540d22aafd21175508a4c3b99068f365565594c1efdddd314332b46b2e77e986dc8c7f11b380a03e9a058ce46717b6d81db75aa3b19fe0367985bd3cfb72eb5dc83a1f400e068f1df65dff9a276c47bc8c1be8df8fc601fe13a0b2616d0f2fc62d5d87131ab86a726b6054ae44be92308ac02a76639b50afc2ef286ad79ec855e7e2b99a9c298798e510f56e79de612c683f6362f1754fdaae9c28e325267cab3e19ae5a061cd5549c0d074c56c0fbca977d46093d06d05c445880a207ddd34241ff64d45626de791bb2ef509eb8ec56fff28cd1052f3e16e4084c4b91c00912485afed89f8b5e09e25f0197d8421d6554b5d6910067dc6514b5082cdce85b42ea516183589c09a0213d948f3e6a419e9c007d5b267241374ea540581b37114ad568d57234ffa9c1628a120828c15b364a46a0d8233fb4d239561ce142260a25d97797822b194ead036ea18d35ef42ee11dedb51c0909d1cc2fa52e0b69c3dc4bccbd87eeb75dea4a8c49ecc57929f760a89a5df3f486f54102fc936d30d6bf022a2ee870553c612282c45a04cd74d9c264c525947a65d04eb7f8cc4e09a08445938f15bf61130df692bf5ed9e22ac0e1480f02e6e2c2587ee3a63c358325802853123a46f515f785483c1153662ac00980ded7410a14390f6ab1d5a0ea944bc5174e3227eaaed6defdc59008a5d586f93815f45beeaae5394c9846538051f83619448faa73ce9b21476b51e10432d84065ac15279f679406266ca95dc8edbfc6b004816a5866198749d36497baeed0629ee38a0124569557b1c63e9b1c8585ba26156b408ea49d5bc2aae1481246ad1b65c74d2d85430bba5c93dc685ee9cd012c5d6cde457fc1ec919e0ae14d7c0aecf4c7e40e0b6f8b8d396789f0225059751782f3c5367f76db234f1612dbe17e946147c6c49b12e39ce5b15745f2d096796390a4f935994530c38072778d1c7e4b8cd10e334580afca43667f1d1c225f06cb77ca0c895c2159a3283069944ddc18c6308e2803c9a49cb2bb439a36d812022930f3d5e40516ef4fb585b72bbd05e2014f8cbb9f4c75fb143c9fbf8d8d5daf037879b9cc256eb496517decac3646403aba95af71d976ffd8282a0c72ab32dc7c9d90178f634594528a01e175943117c93921665b94052e5891634112d193ef6a9c694ed53580d812ea3cfef65d3fce3594fc2d495e9203514d6d3550645435478d59d564bf1af19a568bc0448342288a8f3dd2034f1fa9cd9245365cc6068f0c0349f6fe52db41ed187da537c9878f1dd3c2ac840c3fec92812dc3ae5629cc60cfd017e05c408e62c3b9ec51b3f7c5e95c6b23bf86fc533e68a2c207092f2da040a6beebcd4cfe380b8463e2e1e677d2543332bfc4a33c9bf2bdae5a3d0f868a483872fc65b9d27fe02019f833e3b3305c6f6286c8bcfc8ef952b0a709b69df9964d8a844e386ccacf02cf3664f50ea36d6edcb839cb80d15e330a264e4f24166d2cf1521233656e06d237384d95d16c4bd8ec11fccdeb1b094f82620562cb36a6d53d204f0d3fd598b02aceffdd61c13da93672f81dff9db0b8589f23f23235e13db6b56b2ddc63039e9585ab0e3950b026c301f3ffffffffffffffffff18f61babdf2c5076ff94524aa158152bf786769229252925a793c24070180500000000884dddddadd940ed0e670ebe0efd58fc133620870364a4a2ca2bb6ab964e2f6565a0021d4dd98c8ad153a4a662e9d18a31f7668ad4ad6f35e5e5aafc7121a530f67c0c9fe3a66c972485aff936d46be7791247615adfdc0b22d3d32a5194fa2c97aeb4f81e93a140c44bb7e2936e981814fc8e6e19998376d5d127d29e4c7bf3e8b89de31389448627764fe2594b86c798d489f308f9769dbe77b54e249219cc200631f0a1cbc383482432385185cf61deebbd44e64df0593fbccc05d98c9b26fcd3e0d194ea4b37da4c582a3ac513f53181ae18e235ddd77ba89778fd83667608d1eefee861894f97cbb885265929fe424625fa20c4856fb996cf394a2ceb1d7d44ed58c5389148de83f09031093bb9c7ccb9ed4f3d24092b0891593fc85b8c2b125a3aa119b487bfd33148985496b78b77b3a9ff23d674d56725fbd425d38406321c91a7f73c3a59feb4be271249b74a243bb8d09101198dd04ed355ec4b66d019166430023529e24cbc27f1ea1661b2ecd50e62356f9b901728067284e116c81103198a7894294bfe1ada54362522b53147e9ba910c44985756ebaaf462f59b4824de8544c2020d3200198740a911ca2d36c7a0196388ba5f6d2f5e5c529dd5838c42949d61f66e1eae63228429ca57909673ce7ddf20befa958f5944a67882e0a3ca6dd0547271205d34e08706bc001244024284f88f4ac8080467973a06539647bd0e885bad56cdab3bac877f583d264b51322f8d529f808b12e8d842861f90a964f8587df71e6464f461b77851f1e4680f334f1c20830f69d094f7997b9a463b9148de3be043c61eaca4d495098f9f7535197a287fc6f0d4613376d2630441461eea581af22bd3544c3a78b0dad2452bcb527ee80edb7d7cb34c59d39a7a800c3b64662147fcbd2a79a60ea8bf1d8b2ada49890d1d18b1d2aa1f672ae5d11cfccf31b4fb480bfb141972683b76cc5b79ab947c7140e84c3a9ce5470b220ef9e11cc43720914040061c1032e5e0f9b446fb8b4d24120ec878031f94599dac85d1519b48242ef01f41bc870c3720abc24488e879b6de868228cda0df343f3b63c37d41c8efd794fdf55cc3155cc4692d9da3a74c0d7e8e0f9a836f8f7a2e021969d02b9c1e95636e88db65a0016595a67f3225bd319f84b13cc2f0f18504649c01d99bdd17f318ffac19ce7cf920ae5b366bb20c9eda7c7a9426919b6364f8439e58d694e3c5af8c21b15d77e9a147779a2c430cc94f7b4ae58e2654c547f7e0f1038844e2a329f04303128990150001322940c95104d0f1858c309c82874f524c856f0540804c7c740f25c800039b3e86782dad0de9994824427c08901f2ae30b25195fe445d6e69cf3024a6cfa583d6d4aaac90432bac0edc6d4343179a66612c8e0029e3ffdda091d36e8941d31a020630b7fdc900bf1d8defa2612091732b4909067b264fe13bd1f2c00017298a3438810f762888c2cd83a9b313327713aef800c2cf829f5e5abe74b7fc7094ae0021957a872890ebda77773e3138964478e1d39cc014347107f2040826c20461c6458a12073cac9f256af9a5c46151227efa6d365e698611732a8605b2625f21a3a3ede0fc898c221ef69197b6237172123902105a496bba7c65a02195168552b3489c613ba3532a0d05a2ce91a94deacf1fdc0c9784226a6a4564af330423891481a20c3095a3cd149f3a78f9d618efed1c3023972a840461312a17aed5baccad467070a643021613940a683dc4bff4d9ebf05642cc115dd0fa75e53d0792921f1b6b2f14bfbe59549c0b3af5a5c9a93f594183890810474d4b0e9639e4fdba12324eb4a77ee2c87e6a40c23e4794bbc9657c53ca68c22fce9c2c7effe6c17f9c4c76a086410e118255dc572ccbd2c2712490e1d6170185c071943c06d6bfbcee2a998f710194248cce94e3a6c4ebf5b1389444610fc144e7b74f4f6944320182dc86032ebc4693ff04c5eccf964fcd15727128910193e485ffc44f6ae78c94a0364f4c04d1593794629e99d9e48243b64f0e01473f2d2203ffcd63409f2050f204d02193ba86428d3b4389e46533c64e8e01953aac4f9dead694704620841460ede54192d8f742d112a5df804ba908183ec4b2b9b10327e901b30be907183d374ca29261be3fc22c3067806fdbecba12d33ab85d99962cce147069d9476ecd0e13e56ab20428b2f494b6157b935574f24120d32e40511c891c3870f7d408e06e890486248416416e5142d7f780fb1b0b1894432041159984c05d9ee633278fe132e4462c167f0ee242c5de5ec8185daf7955f849d2e594d76f80f203e1e2091f80f203e780422af283b457d8d791f6a12445c61290bfa151f3ea31d3f34f080c9901e2110e2c3470372e4c821911041a41595860a9a45ba7838151588b062db30a6f739f66b6a316e20b28a4a08adf8617116c22491b840441526f1a09599311f558f81482a8e799a2973908da5723e4450614aeb39ea965b44356e011d251039c5172f9a6e76a8147405022d1031454a5b5e54c5d7dd4489848717fc02068894e2fe4c9fb269acd85b4861e968ba2e6e29192fa350d36e63abec83d5cfc361d0c387af20881f115154ee1d37554f454526811c14d0f1856240c74424148792223b6dfd9bfa4b0414c6cbe769722f8ae5bcc8272cbd4ca3f29f77ce2c0ff616f06880882712df59f44faaccc82b10e9c41ec3fdbfbcb9ceb82610e1c44153c7cbf982a59cdd4422e14287074436a1c6d8b935fe59a9139a784b243b3481973cd3faa4dd56839248268c9e29259933c8e978031210c1c45539c5d8a07ab942287209554f7e924f3a99d279c704b8d0e160f8d0168858a25417aa735d08214522956063a9ce4d37b5bbd04422e9e2478f305a22d901821c16d011c48750e00bf5422291482e204209737f89346fb950914e36203289529231db7d2a36664612058da3548a57ef21e467660b1d0f1089446db11553eaf36c6e81c496c6f593fe4d3a05a940e41166ca3bd27bc553ecd711c9383a08254ead46c91a71d688d2299b7543eb0630a2d7ec22b5f74ccff545f8e3e7b79d255e5dde828822b2aa5f4f426eae7f790591441cd4958ac94da6fcf84144974486959776c70e1d02dd911bd5a2590a7e3241c410e7d30cf1a557632a4f1030881442df1995c9c62f5b75429c62c89e909d4282c8207acb9a642cf9a6d6a320b2fa3d19a15f9d423f99824820f41883f7eac5c577490a22803076b4c893f65241e40f55f2d09ea429efb3e48af821911974eaaf0e9eae14e9434a96b6a8de5f69e18d40840fc8fcdeef5daadad43491488600f121640f5acf68a832ade5597741440f668fe97694a9541e261f4080ec0744f270dffead67f037a14f1d88e061f36c23c64f95bb6eeea0e96ccd4cdac4c2ca7638e7a8bb721e1b7465ea605e7aabcfa4f7492e3af4dd9b4126f3942957211099434a2d7e6add9c463c39fce63f5a3cc70be2561a88c4a1dabfee9e39b95c6a3894a983494f336eb9d40fc8e1801c0d20800844de906edfcda75352ad2945c40de59c5dc582c6199d527820d2862ac81c36559056b1251bcee097f99f4174d92d04913524a24d75fcf35079a36ad0f37692bf177627426948caea6ad4b4a6c2e83b10414349bce26fd2ff513635103943e3c173aef8a4d539c70ce6a037c74497b4dcbe173dd4c703365006d7f43f3756c3c77067204286cc83c7182de2634ca90c44c6d078a65ad7b01b9e471131d461db948f509b72281bd0039130943bb564091569e96bf5091878b58ca793dfc8b8682291a0c817bc77b760b274aee63d24921d1ac8c1450e0ce880804422e285ebfa744a9a1f4ac9f804912e9cc5e496a5f8f7870a086e20c2054df885fc3042bde7070a225b3859182d162a0869b93741440b7c5611a5fb84f8b6cf092259485a4ef7acdd529ef3175f280f5e82081690afdece0a4246633e03225748e5a42dc773a8b8e9011810b14221d2d2e593f749687a2291f0e8e2478f0f8854a10ff596f9aa7515fe89442291ece802c805bc001244025510a1826d157bab5f6695442e74f8109902bafdda95474bfb47d3028944880444a460c768113aca6e0ed51241240ad8c5e0a236e5fc5c520e44a090c959109bd33691488620f20493b5e5786e1933dd9704112754f1d2c8b9d2144bfb451069c249b87a8a267f25cbfe810813cef2269436e92a3a9e8ec812ba1a39d94babae74d2b1224a28fbd47ac5c7aedebd813c60022249b83743d9cd6a26e9e799d9a20b11242832dcfabffa68b64b0c1c881c2111994d068f22935f28032246e8b48ef5ad98296d321b102982ea5f32bac935cbd6261209172244e06b746d4cf7eb41771a880c41dbf11da17fab25f3404484709e9e9219b5329396139120142a7fb48f416ed89c69200284e306f994b1fd335af0077cc9118d1f2a4b6a5a447cf0a667de283a8e12efd50c447a90b2d1cda52d873b992203111e7499576f6a9fd7ee2a3bf87bf546f9057de99648b610d14139fd28b524629a628d1104911c2054cb25b9d1aa437c1389e402124910111cac5ed92acf846a4d7a01082072035634a6c811d972f9462007173a542062037f3305ddcb7f950ffa18b53898aaa049a855f90cd2c2bbb6f7bfae2e99f90d62cc8251f93e69d55cdaefc80221bacbb4a96eedb9c4c27071da4a9ca928b1c1e2754bea42e6d20821f48218af482ce8afdce9d7d5a61f315c91d45c4f0f1f2717361462b4420fba83ca19155b215b410c565817dbc272daa6b35c8c26c458c5a9c77249d1a527e48da18ac452f9c90b9ae7656f418c54a815df63e8acb59f390ff0a11289ff501f3a80c44085591ab3653b5a418c536cd152fe6b90e5416715c43085a983bc8b0b3242d8e85dfc701f3e74c20e88518a83caa80bada26a259e481a108314ed9fecd3f5d933a3c68544320a35bfa48730e555c1230a64d3d756ac69d2319f48245f00914892291e904824928b118a35a87f778e1dcc5467c28347016280c2f81896a9f35dcc353efe627cc2fce1ff9984aca0f54f500c4f2ca2f9de5416a9bac18944d205900b74d105900b7c012403124917407ce848313a714a5f699d96de2a88271249d595974802108313de6e663dd5fe5b8b4f24924d58b2712f8eb85ee88328182c102291488001313451d765903168d350cb6b2046265afd6dfd9c74e7f09c8944928218984866d0108d4f31f805831e675e50858744726656f0811897d0c3ab2f993e0dcd1e0f08d1a1312c71e69fd7bc769da4a62f885189c30821b744266350a2d33125f5a24467a9bf3126915c5a6e4ca5346e5e4920934cba316f4c2a28a5306244c24feb56d9ae84ba98328901893bfa7e7ed3e1bbc32783188fe0535fac853059a5a2180127f11317b8ea1ea12aec2d78399ed77fe9069d3a35b49067d0eea1bebdc7b32cb825932a8d7df1953f5fa80b3cf043035f030b8d7fe82f69b7f9dd5e21213775064f6ae11b7581101e3f7afc78420d2b18ebbb4dcaeece755b871a55383ca5a6361de1a52e150c5ae63ce752ca4c09c68f08d49842f2d6d293d2a73e8f204078d490c261c48e26cdb57cde4d24921a5148e5c553763c1d944c0d282475f45b6dca1d93a7ce50e309f685085d9d5be47edfed84e3cd32075d594cd756418d269c4a8b7c0e5d263c26273598b05bfa24b61e5a93a6263596a0790ccf97f3329e522712c9163594f0a58f0a3ab9e8f405e1b1230239dcc7f6f0e143ff070584780778841164888e184ca89104acf3079db378c8793d9148bef0e2033b1e902308102f58043a56f0a38707bc6011c440420d24acee41a59c4a15408d23f89de5e2dade2ec6de080995bcc2cae6bda4c249043450a308dd8b67a814cb76f79e48240ca84184a3e7c9ed11da09185e7851630895756baa78294891fd4408eeadbb9e4e4a774e022308103058c03582f0fed5564ef6629dd21354030849ab124bffa334d4f8811a2fc6bed0bb2812a213afe1833b4768fe98738d1e9c4e7e18cd6e69abdbc4259214d4e081f1f3a7a37bc8dc7eaab183e388d2986316f394ec8944524307db6b2a3fd3a6ad2c9d4824357280e55419ec4f5b968626128937106ae0a0bc5e1ad464de97cca97183ccebc6ca5edecddd1a36487bc9da7f3d8d29f6138984462d2ecf1554fefc9da53c2140363019d2230427a0410b56642d893967a1ece935b92bfe4978b2a8eb4f684d6d7e2b3ab1d8b7949a10e9731d5d586c716929b23cc68afc159ec99cac6fef0aae37735756fb5f745bb1c6496db3fbdab48c155c2ee141d3ff34c36915b70699b7d69498cfb22af6d4f3b0734d751d4a0572b33f6325d4bd875151c5ef3c8f93aee19ec2ba72d79ce43276f84ca1d68dd2b4cd41ef544a61a52f7d4af9c67eaca4d8f2cbc9b496a3b9cfa3e0e4a85a5132795cfb45e17998fc9bb0526a77283eb11e545bd0e8da22281a4dff2332e5a44fb89f483f5cf5f8aafd7ddc1389ffcfe9838d86f17c27d8b07bb56d532ac61c4e20b3e8f3ec3d8b8ba64d981753f46fd99a68e6c435678f8b65d14c94c14c0553b7615a61828b51d52e5c3b83ee2fc1a56876aa3a885a1959c28edb9ffb3dc8ef5a2a810a51cdf46937e4ba94305d3d575f2ee93a7912c75afda09a34496c32e9379543790aea8e844144d7b674deea7348a47d2c7c8c5769b3531e610a4fc2d4ccc2dff68e289ddefa333d35a252fabf398bcbc7888cb066eb2d63d44528de26aecf53f6784d1106cb7573f2f7f5b33b91f0f8220a3412a1eb66bf66faced820e2cf194be667fe26ef0fc145f5791f6d63edd617340cf16fd4d3a3f2c2f76b6814c219bf4ee51e83c81c320d42a436fc6b6896f5fc78108fad59fe975e107f12c2ece3572659371028932eb2b2fa74570544a9553c4c4745c84633a0230a34fec008d94cbb20ae39a6ea0744b493ac25cf1a1969f4e138539f2eefb5e99969f0e1ec232d9eb29429733f914868ecc170a936647f56558fe9c1d8cef314cf69ca748240230fcea6efb52b1ded47a9081a78b0639d92ad79ad529b3bf0a536ac4ac5729c69021a764854858e49ca9b90ddd501bb4c67713c678771e9607f101a33f9882cdd4281c61cde3e35f6512e64993ff921073c6ed694fbb36704d2be27a011073d6e9b4aee1f96aa24916cf39808c1000d38a05d74f4b3d408dfd3442239008d3778a79e73ec91a3e3522612897b80003a1440c30d89ed20940a2ab7fb34dab075769d534288d805a0c106cd9209cf69d345137b2291f4a0b1062ef75ec95cda7e19204082e4a0a1863e95d0bf1754acb4c104060368a4015342a93c2aaff14786061a105294aacb1d2c9b2c49a0032090487cf80a820401f2e383b440c784c6192eb131344f739217e334cc50def294c6d37dcce83cc806620881461930954bc6f4b57da04106eb5e43883f793a33021a6340b4e2491d0f3d2b96c9077e684022a12186a22991a73e9605b117a08710201bc841812e3c035ef4c8418052d00883318bb2ac666fc9779d000d30184fdcaa68309d4adf031a5f503ea6983667cc8f0fc880861750b9a4df660ceaf274263e840ce9a141b8e841a30bc5b6ce9eaf116d622e020d2ee4e5fbee296e97987a22910082c616b4aff9acab41b64cfc41430b7cdefd127242a3ed68229174f1a38710302a40230be8944fad9ff2864f97891740824880fd0b0f48244c030b8b08513d174655fd88078d2b202653b37b87f30d268964c80b22c0a369588111da6d694b2df33bc2f81e411c041fa0510537750edaf2d5f86d3e080d2aa8731f4d7acc98430715a03a90a33890a33690a33490a33290a33090a32e90a32c40001e47a03185ddc2a6ca55cb5b1ebfc0fb470e2ed090c29ef46bcf7390173b2f51e8724851712d31a3798102eae6c154dea0df7a91008d279464e998da46eeadaa1289086838e1572bd3b17d9a525e4fa3098ebc5dc79436ebb9294c586d47c995baa994dad2008d25983b47ef744fc9c73d043494608cb1949199e63dbf9204c45e74a52053c837e9442251000d24a0f99d5db4753bc9fc118a7b16222ad23042b1aa25b7bb3b6d558aa0b5ee650f4dda94d934888016f10b91d7d0962a348670dc4ef59d22ed83dc08e11c9944c8d3e29e8296461096b3caadb159c37e060806396f7a973cedab30a0f183f2bc7a909a6e5f3459e583634cb59e90fe1d551ea5031a3d5894d8bc15eac38b8cee80060fb2d860e1a3332e4a3625088d1d20af54f3bceda99cf41ad0d08127e3e859affeee20fa80460e2e31da349caccd9623743470700aa245f595859c587240e3067ae79141eba37ad0120d1ba865f5efb145283996c9901efb8019b54896b9a6204537eecfb4c036e5ed836c0717538c21cc988516fa467ada131833649150214d7a2afb0ee199110b2fd54644e96b3203167e8eec4fe6da9e620c901f3c66bca24aad9aee43b507eb7a30c315095d61fa377ed6c6c298d10a4b7f59caa8a1e74977c10c569451355ca857c9697b155f88fcfb545b492b3b43157c7ffc9ed8a452990a1066a4a2ccb6d2f183aa349e9a48241e98810a774678c58586e93130e314e8f0b1941c91a16325444f30c3146d5b2ebbced1c2541d414c04669402b1e3a782ba60066690e21d4bfd21b4848519a348f6e3bb32960c7be6086688a2912384ac8a39c7549756203e3c3023149abcf394f2695afef8e0e13bda87f79080730f1f1e18d2c3013ab898010ac49cb06449df0551aa0af4139c25f565ea41a892cb8f1e5eccf08463d6221ee22c8953994824fa8510c98c4ee0b77d41c9a78530cd0c4e24da435c8cd3bd91f94d201b635d0e6efeafe2163a6668820bca534484e6fa0bd26182199978e52a453da90d4be1199830fa75d77848d7fcec12763a53f29d32b38996b074ff5cf631fdbd6725fecca42dce9cd613254a6c154dcb09b51bec2f93e8e693dab3af52293b9248ff73f44b39c78d12c98eff4181184d9811095356b5dc33ff206407073320819acd7cf81c349148663cc24e363aebfd8ec8798ec874b44e2d836789bd11e78abe511dc4aa86652291ec08e242c080c0ce60c416727f796bbbda53de8b6053de8aecfcb01c1efca307086628c2aaa034e9f0dac9f24c44a151ee6ef563d0fecd40049b82ca8dab09171d93630b1d72987188ee6426aff0d9ac58d991011d4a986108544753daf4ae8266bb10a64f31749f7bde12ea0c42f09f69c7b78462d860c620349d8368b38b2be2ad19cc1044bb7ed16f535e5d8781485eaed19462fc943e20cafd1ebbeb44ef7bfbc359d49b85c97aab5ffda0950e272c2f5c3ab50fc6744aa92cfaf43c69f850b81142ce892f613969c61e0c3a4c97a8392d35a71e12939e1b6325391ddd1979a82ed668ddd53e959a81072b768e79ebf894cb1977d84d287d5aa72dc97fee30c30e57bcbca6748c29c455ea80c5115523fc7409abe990ec96a6e7295542e6e660d83832a72f623d75391877b744a5b2f0b74e1c1015f39fd1b1c24a70482e8550cd7daf29f6062d349b123ab6f194dce0cf87936efeffa6b136b4ddeb1b4c6e9c528f0d99b81cb3df5fd466b906d53279566f12d2d2a606d5f382ee74b1bd9d4903f7a36ad3e818ec346838a866d1d3f944e868cfb0cf66ae2de1bf29c80c997cce3ba7621952e9e3b7b55dc367c990a9d452e2f4499b6dc760e7fc1e4b2f74fbe588c1900d95d5f4e5e9df8421a5a2429dfe7839238221d569d7e92e32860a7da1101bd52ea911175af3c2db1ec3e7b2debe5c5d487c4537bade59b5890b5ce84c4ada9f92f13b5bc8765de485bd246367b5f0ed78f252f9bd262b5948d7c2559fe7cd591c0b5968cda14d26151baa2b984e659039ca07a152d80aefe76ccbebaf9be35f05cf4d7b504b5bb1e5510195b4274d2fe6f79d9d82fd95b35519748bce4821d5ab4af1233fd5de5130291d9e33dc0d0536cbe50ea246c4dff78445bca9979b85558a4e706346a8cc2753ca29a5098bb4b9f471756bc766c25556e9a23ac61f692e01692a96cec61ea544a584ec572f94b258f91b4b42ed9a3c85b7e5cf4d21c1d38a97ad9c3573361d214bad1b235b9e93486718a15aadcf397eb22fbf138964c7036614c10a29eeef7b7a614a338860d69bae52ba36bbf989442264c6108aa3e46330978b395621207408579f2d39d39b2003981104d57bdff4758b67f980708aa7b32b93da109f9c00e96208184078f098f18384fd5dceb5ebb77e80d13ec307e714379594d914cfc72a2366f4a0d1d4e91b3a88fb8e9948245bcce041a9b72baa34fd830ca6193b305c5584e8b8b9925c7560740ddfb7e495f4a654302307a8a084ddb7a78aeb691c7c17cf45a7c9a7dbf30688fb57a80bab78f7cfb0c1ebd1349f387d39f55c0b35c9209eb4d2da45800c5a545d4966a76b8fa9661064cca2bb2464d62dc9fe13cb220be2b446f12e5517148b3ded49f78a7e21969c7040062cf81af751fa3dfd666c888c57e0979230b5a39268ba5da1e72acdbca28408b1b422997784ded1a9f458cc0a7d94f40d2317ea64ed437f682007173a5e20631525997ac7772ffcdb528516e76eb3081d527f3b49b88108de74537d48d327f31e02b7de989f5c5fffb386c0b23d6f8b9812213e85282957edadf2242dac84502b7eeee031c82c1f3308e45636dc9dee69500ba250d9f1729485537103a1c51c63faf47aa7f5054429e78d1b2fc8944fe381851b7ff884dec9cf0ab5b5791f6008f1203c86b00619f202bfe107af94ae3816739cf9981adce8c3996583ecb7ec6135290237f8c08b3e955c83188109dcd8c361795a467b8e49d7b3c50d3d245f994be376f27087ade49b5cf4eec71d61e80d3cf09df39e5deafb17b16edc01791a634bcc979cca94c2458e2a5c104007deb083e6b2fb9d8449950f81dca8433274bafc9d3febe28f841b7448a68e16bd2fde5786c7101772841b73f0cd5cc4eb754f9b77430ea570516debf731fa4b243bfc87fae031841b7140c6ec2535451ffdd96ec0c1131e6faefc647aaa76e4c811c4fd875ea0bd0540826c200701446871e30dc5927231c5d6d4ae71c00d37a0c45394b70dd1a2466dc84fe58d57e242893f0cb7c044886e91c30110082308102f1c035fb8c186cfcb4fc6961bfb94dfc08d3598e25dafd26ba638da1d098c1b6ac8c6c3f24ae5412870230da83ff97193121d6365be10a2e3061aeee8e92eaaf805a59b335825ad74ae7c1ecf4166b8c3c7f18c31a674dbcaf0c914f1a43fa691274306feea3744dce5a7bf8c81cbe12f074d1944348b51881b623879d0ce9636b8c58d307c9dc355fe61e80e1dfda301ee1218e213c891830239b8d0216403436484e10618ac3057b23e7d3b4f4522b9f105756f7fb3e3c90bee254f3a594c499e8abbc066a9ec503a85f29473830b67f859f2e03933e53709438304d11b5bf8c7f287fec898b79a1b5a387507fd298ae98f2767c113a1a7ce3c85053d7d949cb194a2a6be7105ce84d0c17b93450b422b786541c6b69056015bef199944dbd77c5478dd7ee4bf42ae0f6488036e4c01eb51f99ab45b933ec81021ce3f1aa0851b52303dc934755e55b116ac80c7abfbe0b16307082c9063c71030302002861b51c874a96d5bf3d2a32f144ab252126a2e67db929d70e3096a0efbdf31279db3e51b4ed0f227dd3d9ff7dfea1b4d38ac78eb29b92ce1df206e30c13b9572e84be21b4bd883696c7255d7cea3129e151926e38c0c7fa71b49c0337b734ab2dde206120ccbcdbdf47561cebd7184ce4f592ccd56316b95811b46e03388cc6429e469c56e14e1ce9ced2963ace776211249086e10c1dd7c26d39ccc99c2786308a7fe9fed65ec1ce36078033271430869ff24d34458a64b6f10f6cc26466db29cf6b4021d720308e90af25c647990ef413b6efce09cb7498ace9db693f4860f90c93264f0acf7e0dad29c425ab218cc9f4c1a71830797dc5de89c561f7dded881a17379524746279dd5011ea7dd63dc6d4b329f2347ebf8c38d1c58fb9dfc622ce4aa7303072659429bbe1cf3319c376ec087598a7a49e7fbbd618373879141cefa94c7ab1687f991494bc58b415e264274826cd0e2f03b73aaccc367934a99c569c654b84c222d47d3c3862c4cab66ebffe3717e73808d587439de33e6d6fd37a11778d980c55f3ee329d79e84c65f619ff7fdda287d32c81557f99a9edba432674d2b8c8f4985f9f7bc793b91487808e9c18a8205ef3d719f17de5f85fa6d6f21e4c88c3157453a25953f68337931fd4422e1e10110a201d0a12386146ca4c22cf297d9521257e9d6e1011ba8d8ba42799a488ff12a1d0cb0718a4ae500ef8f9a8e1972fbd2b2610ab4a5fa6cead56df58611840b20364a51ba24bdf2cdb87cdcbab0418a3748abb29dff1f088f15708f158cc258428feeef2a61418f830d516c2a3c3d4d93585f58602314ede84a3f363f5e1530c030820d50ac2dc24bab59cea8958944f289bd42a6577f525f952e8f205dd8f08441534a2a54674aab8b60a313efd899098b15f3efccd11490820d4e94fddfbe3dd68944b2021f60ac4472021b9b502e5eb6d06143138aaddedf89a8a0bd9289f3aeaa29616b5dba9c482498c02cf5658c7929994ba4cc4a876c75d39d62362c7196cba7534fa2526c54e24cbaf488f2db9cb7a4c496f38758efb2247aa15f089944e92e5bacbe6496ac93846d7227ee92a5145c8cc4f125ea31a527efec4222b149a6a4a64e79920b136c3ce2ac94ce7450495c46b7e10844c634da87de4623161937452f4d62bbc1760ff23c86781762b0c18882b0f0295aaebb936711d5693219846ebebd3c9148c208324422d99163033a14716ecbdaa51d9e482436125176fd5016530aface4284a2b1f4de57d46ed46c1c62b952cf94f73c5454ffc2834824c78621d2a35a3e6f7ad2985bc710f7807b102e1c60a3109c0c712adedde4a7ecb041084b3c6cac78de955ce4e30b1e0f84c7eed8e1437f04d1c0ab5f20070872582047fb0f1768402209e22b08a25ebc77c01b48067ebca0c7c718858d419863aa54fc0b19d18f205059d4b3be56e87dd20f203c12602310d567cc4d26c3a8b6c7062032fbcf269696e2ebc1431036fe8032d1495f082ba95f4b2427b0e107445dcc13f76a29c56a1236fa704c19ee2dd75a4ab2c287747f93a9a4f7634db587931a3d59fb20468f69430f65516b4f669617f42060b00731808d3c744935a6a6da79e710036ce041dff8178ba396a67214d8b843c24f4dc918a467d26c626cd8e1dc9fa2e9594f3c1da2cd831036ea8092d1a4c5f02533729c48241ab041072ecfe5b895f294c93cf9838d39202e6c9a107edf977336e4803e952a87669a7c8abdc0461c0aa52bb73b539f6c06075b2c887fef948d3760b19a4da48d8c7ad80d8f4aa3c36b836d976fc33ba9da6d6cb07bbf2d88cda160630da5d0e1fa74642efa490df5778e49e74dcdb5540c6ca4c14a234e47cb5f75f0d840c35df2beb4e9607ab43dc3d136c6fb73aff2069961cf289be5a2db28c3e9826eb5a0a9f2a96ec2700be43041bc84e116c8519a60830c9ae950e1b4df36c650921b64b08a1db25426867c3dece7e4f94c6d36914880f8f08044e2021b61f83b5676534109b9a34d249202402007017404c20618928bff4c3557b9724cc80f0a48244286fcd02118b0f185a267ecfcb4cfefb22d60c30b8f52dff3b1dfe2de3ce1b1ba0fd0818d2ea47673d2f4167dbcee8944c202f7a13d8604d10d48245f78c124b0c1853bdc96bd5cd01fdb62630ba8144e460f135b6a2a607861430bddc5599ae8ac1bcacbc231555b358af05e4ba70d2c5ca7593e2fcb5236151b57583b5d7aeaa4a3fb661eddc30a8edbd7c8cefe972855a1d8f6a1ba46c6286ee2810d2a18167ea731be870cf2f801a4878d291462f162cde718ea2a1dd89002371bbbe3b1c3885aa290bef914bda8fe7193a0f0c7dbcd75101a33db78c261f7927e6cf6bc5f9cf0b5a5d2f81f46c9cc9bb057f2b06134e791758ec006131435b22366534b585458c7b9f02937db1389e481f050027e25d49c8c31cce23a91486c2421a9f146df9ef88d9c6c2001b5a057c53da54c6207e060e3086795975c7dabf9786d180171ffb3f8ea93177f1b45b094ec3d2db161a29530d820021b4e9b8a99dbd663011b43f8d287b7f978ec6a6b0f3684f08e07d5adb6135bfb4422b1118447b7eb4ff32aa5de8170f4945d7dbd37f3b6f1837b634c277cc3465ea56cf8e0f0cfd92925cd6423e33164878d1e9882cca442a71cdbd33f9148785cc0060f50a673345b529a92a5271209086cec40fffd142f7597c36b5bd8d001fa3eb667cb36faabf6c2460e0acde1947ae51c77833c54053670601017725d3378b6eabab07103f3c55f9131f34be6ce1c6cd8601b6d3a4f69d0ba96520b65bef3cdc48813ffd3a24fbd75d9abdc3e45d4988549b33e98ee773d51cb02cdf1c7638cd53b0f0f8964c78e20421e5123166aee4e2583c74f67262c90fa7942254d53f997579c83708b76d184caf103a4c1708519bbc2ccba3e914824355ad145d950679e7e358c2612c9163558c1d58aca21f252e4aeab584d7550593b66e4ac8a3a861035fe6a76964ac5b7c9f2bca6ac79d4878aea7244a74d7273a7d829de6062293e590a2e7a53a42d7a3b962ae5248315a8518aced4968d06ed509ae6a206291a5342ab7774146617b5366e2affa7df420435445165b8d6b0990501c22314a7dd3a996f1f7e264f24921d61a8018a3aef8bcc1c76a3a8c1a8f109b7c62ec6d3a03c673ee1e189734e221ac2663396be13bc75fa73cfb631a5d24422e1114690219c488893efa1772f56524d784ca0c626be14b5be283a55a67548241249036a68a21c9d3a77335ace8a99d84aa694526aba303563023315a7c2327c8963cb28395fa56abe46a186258c356fc2c38f78782a81e894a308a1afc2081d25d6522943ecd4733d651265ce2763b4bb94f54a92488c384b1746530aea14093cc8139775e7744c3624527a696359ec0ea77f444a573eb4b234914878d470442bfa474d54f4db20a8d108f382c9dd6f0c99d39f8b1a8cf8739229673642ec6f2612c922caa9163e7366b611d6442209410d451443bd6711eaecfc2b5ef04844657954aa5129bff752a00622ecdf7c31658f8f2919a87188d2698f6629dca26f882e73ba6b8d85fece14c2d25c622e2150ed9e1993f7c6b73f085dbc55b367b0b40ba2cfcca38410bd44c2458d40e0bd7b4adb7d8040890efac7c334f92985d4f88339a329bb9c1372fb23a4d4f0439ad3dc65ce2cd56e2641bef0220535fa6066bd712d352a7b3c24122f5a20881a7c30eb88bad9e02154fd3dfc7f29f9c9a46d6e6e3d9cc4aae654a54c5be5442211a23c6ae421911a734ecd417c27b5f2c00316664e339687f8482712c91d6cf5a0b45209a86187f2be36bee70cd7741dac9c2b65bbccfeb8ec4422a1c3d1477d744f32c720ee8917732895d9e9b835e4b0e79b8dd1324ca5bf2612491c5e1935e2993ba2c241db3215bb4696d9e93d1c50e30de5b2d4ee31e531bc9a30a0861bbe79574be949e6ad801a6d48eefa5f0a7a39e38a266cc862d21a9b82ac6e2550630dfc8f68d3e6673a29d9442299400d35a452b79bf4519b4f262712c9026aa481d1a544f45e36dd619a482412091ab4cb55d2ffc63e7d0346076a9c2121f533c8e577373750c30cc7e518c4d79d7ebdd70235cad08a6ed54dadf192bce0173ca00619acf2b9a8adede9e699482459630ca7526abc3b3eee2a67229108e171811a62585367b6eff83795471389044843a046186a0ff295bff383ec7822e46a802169969fa2e9941a1eacf10533884a6b1a936a78c1e4b963e474de1c6e6e8d2edca55c2dc99a03e7a9cf0ecaaa94260140088777d7b99223d7e9038020d8a2716e77767d7a010010d21a3ae36b50f1a23e00fca0b41a5d2b45f5491301c007fda6785f54efbe4a01a00727b11984cecd3e214e00f0c028ff19457e1c003b70367e48516f5a3da7004007d9d588f1f053a67e03400e30dfcf9e5463b8785a00e020216adb9762caee3903e00625bbe43d1a636d8f050036f82ab35807259b64666b51d4bc4f233e976a74b438fec8749e4c26a1943d8b7308abf68acaa293cf33fea1c5020f4a08d55ee945a9c0e2e8a21de23d744cd7f58af57d739595f00a1d5720b3ed49ba58a8536d2b1ef5711f5308b1e2f03a6b4966ed57a5ab4073cb59daaef065be2aae7c694f93c74a6f31159f5daa66ca4b22f4cb030e549855b3fabac7d42e790aff34f4b37c66eeb79822215c537d6799b9582945ba76ed6412428c680f293aaf4c41563e95ee62f4d59cf1a5eed70d7088c24b3a1a4e79d21cdd42e1a87a34f5dd82e27b95edd11c7141359f38fb0871f2af2334f3030c1e1fc0e1897bc3ac5c6b8d031c9db0f655c5e72ae3774806383861bd55d0367e73b14941706ca2ce493e9eaef8acbd85700087261a6dda33567838cfa74c24d5e394baa4a4580c61c27c15d53327d9bbd7705ce2f91837c74c7ce5862c919ff66a15a19e47fc95382e29f5961b745d644ad41b54a75d4ce7a617c731896cd7da378f86cafa4ba254d1d4cefd866b6622e16ab04d6f49ee8592c7d8010e48b4b9357cca7d8f707c3c7ad676a000872370cfb9e2d6bb7fd894469cf3f7b4937e9f37cf184668395cb5621a4b59049a748c56669732f35da58843fd55c7f7a8d99e7024a29159a6fbe31b8388476eaf8bee381b94aa944370e949e306a5b3641e872118b5fb31fe31e78f7221ac0fe5a2742391b0901e5e08c14188ba368c29a53f76fa3e884b732a2183878228647f0a472090e1b57374931f27e6227000e22497a5a6b3ba848f40c0f10776b3b77a76d0397a1a631038fcd07a4a539d29c7839c0481a30f8690c15407b114dca414c0010e3edc99d352d76aeda8788c2ee0d843e16e84763a391dbcd2c3df7b232b6d281584120b70e4e1b0a2abc252ab8a1ce1c1df1a798f957761f338ee801c9b7b7153fd2b0d871d4aca7412efd2ee31b60e40600b1d38ea60a58ae9f4a5f06ad1e9606b69cd5073f3682b8e39382e22c22ad535bbca020e3994438656d5ac656625088e38f81ae35bc7cb56681f80030ea98cf4244e4f38dee09b87cba46309031c6ec07383f2d24d255310ea00471b32ffcb38d257b35b0a071b584f699b93ce2966d1aca14c22f36f052d3255921ada20e4c6f9186d37bb40c091864f93523233a734631625e040c349aae50c6fb3d9cc83041c67c0336d8e7996355d5d627801871934659ff28d96b34bbd0c8655f691353235e020832754bac650e53ed9eeec0c0f2516708821b5d1ccff2c969caec3709e52d6f1d3636473c0906dcc5e7e85bf90ce7d67af29b5d6a1177078c18aa25974b2d7aa8e71014717d6ae645fb321655365030e2e9862494fa6ad8465b8706ca196efa063a7560e38b470f0943cdaa51a1b91e2c842d66d72747b909e298585e7d4b4daed5d18e9b982ada234b52a9dce555bc18ff9f4d7ccf2018e2a243fcf3f7395f69b4d85734eb79eda4d5b8f050738a6609e7edcaadceb9c940738a4d0fe08cb4afdd32d970c7044e11d7deb3d5642055d82c21aa33afd6c4cdb980b8e272ceba9794c8456131e1c4ee8a4e708df583a3cfd389ac0752ee5417433c50dc2c104fcaa6d2dcaa99a3105192244008c6309958c9b6a2133b5efd3001c4a282c8e1821633a20470374b00047121ed3a274fd77d44c1f1292325a2e75e47184ace4d229cd6b3d2b71186119fdd7a52be8ad2ee128829935b8e78d102696c741044484b264b1992e9c7608a68c8b6df716ba3f1742299c38cbaf943265078e205c41e3c6754ce300424a97cc49df54d5c71c8e1f305a6acfb7837c51693070f8201546988593e34105d94422f1a13e44080970f4a00d9b0b9673fa205fc5c103449e7dda12d2b4ef1bf2435941d0011c3b3876c6e0e12b7ad484f13d74e067d9a0d725e441be90008e1c6c1edf9737cda64ab11e3870e075ded8f05015ab4e3738a8acd1ac3f85c306a50c13ee4976ae6768466a71ec15397fb246cc43b428a6990baaefdc633b0c189905df9dacf2f35e7a8b6f31220b3d4467d93855e527732181915814c47c8a5a5284c5961753a794e2cc7ff6158c7e986e8a225798d485f3b4bf1964c709184278fc1869c51d4e36e9fcb13c9d3f6145f24d76a97c12e3493b81c0c82a8c1b0bba22b60c8ca822cfea5fa664ea9c7d273b3a8806b61849c5f515a2fd9eaac3694346506174ef12299ebdf4ef491030464eb15f45f3f46eb22e89bde8a142464ca15eb95890b92d60a414ece6cb568d921f9e4d24921d41bc3508173972e8f0c208290c15748b7e65b1bc9f8944122488f3f842bd90486c6414fd9de8ac290633fdd88e178c88829141c9b92565da923e91481c30120a63fd5652ed57e67282a2d7ff1067329527ddfb61e4138eb8cf962c671b99b6c90e8924c888272a99e292558c1fcfe3914ed4debe163448d15973f2430312c90f205f8c70c22043cc7acd3dcb2ec1c8261e0be23b44c3f62f4413088b39eb6f86f6aa2018c9447749e79bf0cd041356acaef5ff104760e41258ec24c48b6ef94aff700ff488254eee9595c1de8944d2398604f1090f510ce468401f462a61e7a04b4b5e87a86c0ac9d132ec304209f773258ddbdaa1e774408e064c22f1ada4f156f40a189144e3b1637ac5dab5e84e2492914874b1a7b52a5dca9b3fe13164c70e0de838a6c450c208245266ead729da3cb890482430f2883473723b114d96325d801c4d01024461c411a6d1ba249406471a9158bcf670cd0b30842c1842249234c208ccf57b75c465b0fb7c641169653c91c1c62d962564471451fe9e8add59233dbb238940c6b739d99b53ebeb101841846b67f52694aead914e28307208e42ce64a662987eb0c9106b5f669d959f47d84c410c2482152962a8b6dce65ae56054608517cb9ec7b7bafa29b89440281914134aa7f317ce7ce887d44106a4af98dd11dcfa5c04820bc9449995bd29a43894600612e7baf542aad66fe47fea0ed85c6668a2362d9442219c1881fca8beda2ae3ffdccee037a33e65dbe3e4b96151f0cca42ef8d1eff98973d9cf1f2ed060bb9714c3db829c798d2dbb92c4b528ce4e1b078d5dbd4ba16251eee374bc2e363ce5cfb0e2561fdff6bf142e8ec6030b7d0b2d219c4ca7530343b5c7af58ce2321d2c0d9e2e2d2be8d0e2e4012373f867776e3df7b389d2881c585321eadf979138d4392f5e0a699b221a3868a5b552df9e9c5166d51b5cf92473663a8352b98f1137e839c4d4d9e55d5b6ca40df6a665c91355da2c580a1bee8ba91d634e18236b7873df7857decfbe5730a286f3c50b4fa1c4cc5db8d290c78e6fe80ad3ae1f0dc8870b2eb2e3c57bd21846ceb0fb9e6acb397fc5e698c19339fc5db63315635019acaa24f6534acb2573322c624573f66f528db5c6d0c77c9bf4c85ce8696270a4a70afe39588739151e35120653ccd72c5d3cc6c777142f8c808153a52f737f27bfd9c060e40bce98b2f0624ac6acd50ba54c26f34e737d69fe08235d28f3f87ca853f162295c38e8d367df7ed577d2912d60d749a70cbafb2eea03c8f30823c8102d7cf1fe41792e25c3833a3a9003c8901f1498a184912c9429a5ddb85ff236e61dc841011d437e8031f100f7f031820594ce4c4d59ae767621ce43d0c815bedc8e9e72b84c4faf157097b11099ff2a7dee050f1f3e9425922160600047aaf099c9d21e44a6cc1a9f1480002354b8fd62b01436275b1933b0e38b91299434a5aa17fdda9ec72a5240e5bda76a9507535e14d6adbc3ccb6d512c1d818231a3540e3aa39ad9cf63e409a88f75a153ed497dab941127e4a12dae494f279a3310469a50a7991d296a33b633019527561fb31c598276fba336a845cf628e28c1b8f1245646fac9118e240129a32d167f9a63902f308204846d6ad12963f9091108468ee0c59ad8928d16679911239c6448b90d9f6360a408beba6e95e66b9fcb6e314204b42c06a95b298fd2e0c8103cafe0fd97eae2cc234230c5cc792d63efee974682b0c6160f1af3a58b69331122e4022340d0d26c5cefd9dc0a1f0d8cfca05babb852593be99e273b763c400706723c2007173a74c460c407bcc512fa82cca58573a4078d4e9fe2b2a7d35b7430c2833b7466cc7096a2ee144422d931b203b48e182163c98e8610074674c079a655ce49058b8f0b61240798ec529bf2b955d9e1058ba07fb8070a6081111cac9a84ac9b7c3748acc2ac5f675e65cb880dacca9b31987f32ff522dbaed3cd3f7dfc9727e74e0062d16bd61af926d7dd8cf64073b088604f116ac8075c2801bb3a83d841499844c4d8511840b05dc90c5e3bf62399fc1f37c317870231689d09933661326f7770e6ec002216352cb6f6336c66fbc42d16e3193bcac2fe2de70859d3769c94e7f5a74a315cdc6de185b5438b5d6e4062b50377abeb336a6fd7c136eac222d53496cc56b1bf10d5554f2b42d0619aebbf9106ea4222d324acf858fc8893750d1c9d1a93a543637ddf0e81f7ae314a5b7e0be9a6b53983c87d95817117d5d29d8d49a3f25b356f595145e7656544f723da74c821ba3f874d6383262314b8a44f1a7b0164bf77bbef885c2a05fe7f584e764958122bf8a23f386e70d727ea2b1ca71518454b994efc10d4fb0597f9ea2668ff194dd7aa31375d7e6a798f33dfbf9c303373871b0cd3e7bf51c5fab4d20b656ed35b386a659135bd0539562ce9f37ae1b99c0f3535edff7a951421389e4062652224a9c68707900e9c98d4bb85e9f15fee9bb49fce38625f0eb204dab3a66dd180f207da31295ca20d7e28b65985c20e00625fc4e2f76a1cc63d0e88d49a05489d33d5ef1d5441f02040446b821093f48d5d2d531bc9e68801b91d04c88cc3988d8a41f24cced29ae63768f50e4fbfcaca8af3aa123d81cd747c798694462f274471b112a5746543a6bf6938692b5d787de5884f1ccb30895945595ae0537146186ee9bc88968c57823119eb8e839019169a82453d350200c8642813018000480016cb70e024311083038402210486412b98438dc03140000473e2864442c2a281a1891c802a140200c8643e2501808a2200c022986e36018f55a3a22b82f43ae5dbca71268b9cc2a15d6a34abc8c19ac83b95506b158cd0d2976af9a5562ac8a642de6656cbdf5352db24d31261d3b12273c345cf9c1ccd6314ff7b47bc58a3130dd66de9e9f39e6135c31317d4fdf3158f7a5cba86d7b91e12ac1cb5c598c74ff4f4936d07167d28fa17b0c3780ea0d01d8e7f77f51bbccd9d5b7bd982fdec4fab67d7e47316f6f448c8787f60128d530f8691b520bbf11c168ed691ca7c74c03f1e17ed8ff1590c54c191b68141141c287f1f193b847ec4fc6cc664d1b4b145dafdcf7bc9cb40a3d9080cd24c1caaa47153d6e7302c8adb1b75b026a2ba42069038e352e2ac4c1c6cabb09d05b1784452d07e50f31dad791507b0571a6897bc362dc359c428a7ee17fed45f533efdfa14c6103e0b9229c8447b97008f148dc81ddaef52ee920732ec76c287d7cdd877245f03fda5442fdb045b3b4977fcb9abb1cf3b44f0c7c2333b7b62893f270b2d558de54029c7426d3bc7b89a6c347da55dca66822dfac2a1b868081542e5bfd6a22deaee2f6e52cf9ae99192592e440074fa97fbe1b1571b7c3be3ae4ce084d8fe0a94429b2b6c1240d9198c8b668b18f5f0fb491daedf5c0fbe6c3c38b326d740f318045ec911a8ae4a9dbb2849c01301dbac371f38edc8131fb215b3266d16fc33d1ab5e2c8b47438738ff3986aeec5f8f2157f1bfabb953ea05831df8c85eb895a42a5c42a44d1f6676b93f8e619461593ea85be5a256605eea3067207fdc74e66c98f5f71a423ce6bd7597cb3989519a2ffab9794b4a7d55731de31e080fb31b85d8f81101a4a297ab56ccabbb43fa4a50dedffff509ebc72be295e97d5f770de337ad22823fa6dfc1ab94bc8194f5e9c59dc7da4f1e6d0cb608146fe0e5fc04e011bba8c90224279e91523d4ae2ad9b1221c238bf7b048dc23981b52f43862fcccd04a34747cd06d3452aa40be622b53f3dc1d7cf4350cb8978ded2892d9dc0ebbf8a1feecc9d7ad32261dd0283704003c9a9434853a25f72fb298fc220c2d39c54826545012412ce4c80c3ab0aebe8517bb797ea5252b29a032a8f6fc0bd88d6886dc310a714310a157a36e969e5adeff60a171c91b6ce2ef9c19fed218bf5f19acaaa9d863512b4112e0bfe1922662deeb6d3afa92e6d1543244fce7e7d04b683cf18f1525a5ab773409ac74af7684073bfa8dfa3587af11b84d6b484533785d49595b8d61f13b152b5b9743660081d61d314a91a8e9a55a75e262d07918312a78da14ac96b9d14d0a0d5efc84bc5ef4ebd42b5b29ebf82fa7c6358d3fdcb21edec31cb291da30bb6ff127710dc00987bc28d7e99aae2e585a28709c5bd470eacd5add88015436da1ef14965f756c02b23bab2811d22bb154b8e5a42d7417f1c235bd169333288060e0ee73fe5b370f0cc6874514028da39a82d338f456ce2d68aa9d96f8a2aac310d95b41a6a63f2db42e16720145c02f4e49566ac15c785b5263c529f82d2207c39d0994f0961f317ca084163e82c2e31fc4fdd06570e3fd5aa7a01dac5b6933885a7a0c127b495904239630b614b02ba3ba1c6f14cb743c0731de6d91d6ee322805801cfc78e1c1446d7713a9ea95821b93c815df9386ee691f7c141ec9209609ee1f2aab20d5e855b260924f54e00f854038d40a43ec0c8134cfd12133a31c991d9dca535e6761d97ec0969ca034718eecaabca40c9c4d4e8ed042c87d6aa9345d7c4ab4bed01be928c2ff628284b4dac36db1c841654d7ce892376ac43373bb7b7c2ae162ba2f5ed5013732b08efb32f394d85d395e3ef94b9272f20b64399c5770b29fd38f68165dd538c26de40ebd3b62c0b2acc8b34514053a64a96769eabcb600aa3be87dcc74507010187502206a2516d62fc6cf060c4f5f2e5f31270daeb20bd13ce536cf989fd3f2a2da60852c701688a22503f4465af6072970f2e2c5578bfcefcfefa6e57f72748c59b1d0ee5569614f6df95b09cd42584d94a14b55975d44d668a68f7bd36a44e46733aff137ae0a807f07049ac44ee016636ab0b396d2b0d211468725b6933c62f5b62aa5f4d4738345b4426005fcc5041d1dab64b5295c58c2261189ecf8d2ddacf192351c5558ad98208b47880fd17600df70d40969e61d273b71ed119089f9fe9d44a57648b63658f9011839686fb1a485aca8c244a0d0c0b4a15c8955e6cf2bb1b78c7058fe3a01a4b830abdfeaa651d8886e9ca772867ea0400fe781fed0635c7df830dc95154a46f396e3ab92b06a2f1425a4c83dda2ef23303dce6766a27176cebadcdbfade798eeb9209989941936b447d57cb1036199d04151b93e3dbf98feed4623d5235983b2509b4b5202a9629fc26b0e3864535f58f17b9a4cb5e4876bedad4aaef3454e89cf0caf4e51a88d3b9553619c2c86544444d00b29a0143a3b3b6d10350f3688461d856b141d69514bbbc2da3654e3f0681eb899c2f82c3d6f440078889e991669019d6501425714f8dd10ba2be09cea3a917b986fee27f0830e6a5a7bf0e2d1a6128e1354a47ec9bce3003851ad4397b0fe6af908e8410bd7a3c466392a75809008e9d94c2a14feb6224c16732748c4b3bf20ef766567e2b2cdc2647f8c6d48f6d386222e24fd52e11de77736e36d8d81aea87ca5fb034d92db199709845353574fd48adc095f36cdce4171212ea8f0ad3f8c6d1083f2de90e1724ed6ba4dcf4d607c6b3f16f2e5bec8c11ee57adf2a6a03c09226fa9da2c62627ee85deac4391d8fd757ea385d3d5f1f6ff1171ee51c2dbfc059c7b7e3488b291cb8919cdcb6050c47f29b8c2827e83dd0f0a1ad8680daeba0220a4650bb1ac6071c0632a002e29e0662379e74d27da3c7fd9ddbb8302a30a0d59dd5267a990231ff4ae81bea8c6f0c35f6dbdafa7eaab36d9afdeb193f5e6a26f6dbb9fc076c684bdb5c5abece7c164e60a2e982b6e500fc188832585f00282b1c0eded5e8eccadd01eecdbfa415f81f867d8d8000e6ce7587cef5e9cb07f5a0514d18e22d0dfdf79830eb4d590608d3ae60be56d0ecc09fe72cc3973aa4c532b91242b4b08f82842173feff9333da9abbd8aa06a26ae8cbcd9c8099235333052d498e91ab65f798827e80485d4a5d57bfe27faf162e569cde3f12d129e6387707764f76a5070382721301389f501a102688699307840e8328beb89f00097c961d586c06471778e3950c4091bc19d654b4ded3fbeecd1152be1a83ef3491284773dac50d7c420d81932986c1301a7f73b07f91ddb7c11ee49073b5bbbc13d870ec6df847eef4eff806f6f8b56cc69807d1f06fcffac1a5d2b3fd1fa76856218b9a7672bf5707104d2e69ea7d79fcdb69b251091e30554cf378d40e2e456e0ecf0761c2514392ad1e2e466d6b2d0b765f30ae11085b42f53bdf23e7ba81c968659a2c76372bfe0912b7a74b0106af1c3f97c79250d2a66077847a77ac904e966177928db194d3ea09f7da48943a881b3369887e86490132be1b0d88bc0aa1ae8a5bd4915d0a6766b23761c21a4235b3f210e4b48a8200cd1654ca769fa693b1c1c9494c956000b4b193a4d2967b8f0b4cb1380cabe1192e76d2ad9ab5a31950c64cac6b825179bd754647a349f98a2172f7afc29750a2fbb3912be9addfa2da9146bc6da9dbbcdf625fcd24521a2402648ee7fa457b19347195c31fb80c7b380f5528b1431d4900277edca969ea285f388ac83ae00fce4fe365b809546a8bdfe56456dccf71eaad0d8e346605cd6c104ac36c860f50e12c3d5a1c8464815899ab657800ac66f049ee534707bec0ad8abc43587c8b41b7543365846f038f5f0aa20c2c216305505b61bcafe0107e757ece96b0e3d215ca80ab07d30c56670d01b33fc4f9b607bc1c36788ba3a795bef4a0e7f44b52d381a4b14e320c74f15cd742911d475e92219211ae4d8bdf48749f2acd7f90874ade6c1ce17b0b85ff219ad5aa3556f13191f74d6a3951ecbefc2dc2b0955d60e194d869a53e429791a057df7dc29df2a715829d670394d884c6ba889d89574674daab99089405703ab341031331a25a3a743cae0b2bab86287a955e300614c662cb118433e7851314e094b0e32bbe0ba51fe5f8b81ac249cbb03c189c234047d09034e6eda6c1b156928c19d037ce9aa06592a9629452ce7ed26a84d5057fb48129517869f61aef17624ef6140e7e5b5c44127d34055d24227f0267270d99a64ee321ae9a1166974b269ee051971a4a1de8ff3875ba8437ebc4f17fcd411d419fd60ab7407a9d65e8d1bfefc122f5ed71377a1a3f0c64576466694b4a2ec4104f082db448fe7401886804858035553a56db88b723d705704005ada7677db66996ed2017bb071c7b155036f5b7dd02b77aeb1bbd2772104cc3ea0e654a4aa574345e18ed649614a9b6f9164f60f7f6123afe3ce6db5dde8ca623f6891e015b47511fa755249799cf5111c3a9ab48309800572690bd0f8fab7facbb4c3b7666fea9fbc36b3e60196ed3e6772bf163a9a3586b588efe51d964868db3c3a9dc5ff985bfa730035ff9d1bf80e3788fe1aff81c3424ebc537e4a742f5a7ea764382dff8530f8a0d7809bd93b4647c6be9d05f5544efc50197b407aa98ffc5f0cfee6119fd8181fecc962dea0adf6e58ad090a31120cbb23b397d2ee03404e0ff5b6190fd3b3ee66e4ab9c8667ea1883f327eed3fae81f04def75442fb95d6617aa293c273dbceade4b3d8e9eb0fda3c94a61423828de86c51cb41b769680826a0c7cd248bd7084ed33e52976a9c232585d742e7f449829de0387438e896275ba6309710ebc37e993d110f9f8ae24ec54f30103f3c7cd1edf2f5ba5028e1d50c5afe8596f4eefc1af0cceeefdbd9cf97e6560437a500fdba6794ed21fa333d74f5edc8ecf3becb305eecbed5dad5c4ccd358b2942c345e904be26ac6763a2ad1396984c88698f571620ab9aa6a27bc4e7630ce196d450a1739c006bbb106dfe3c01e902742f44cc229b6b070354a7c727de94125ad2eb6ac67271ade35d2e13d984453fcea56336f58c7c67b1d63b2865d05e604e2418ef48896b0c0ae10541f08622f292f37b4e9a38587e471fbd532003da29d32169a4098a0957cd15421035cd513a45108853f6253504899db865ad2486e537b2264f2e18079acf6c2a851da91decb5942ead463f363cdd2592916f67c829dd8aba2f32b2efcc5fe1487fb95e7506079f7fb50d96c7596167468e3916d05c5032a7863936cdc08690cdbf2c5dd386380e8cbce63fa4d46b9953d4c8d3a23561ef1b10d82810c8a73091e4a9f5f13405fed85067b16d2a5c736c86efc66a3fefce9a31785432a433e5e7de0d4ae5f5c644b120e491ce337e717462a13ad3d573c4fd2f7069540c4327ee841f4441735154fdd3236c8848169e7c02acc59f494da3a10a472192f209c7258abbfb41f3b49be311f0e9e596a74cec0f2bc1538ce73ff7d79da816581dd4d7bb23bbd43daad333416b20089f39ca812cb35a1bdf2520f00a20b073cc1830e472b7fcb7d34451f6abb608e58902b981e69c0a12f5c2ac4cda77e56991097e24c237f27bc7fe4b24ddaf3dc499878eac221e4ac014679879cb660e365a7d0ea295eae3f8393a55447fb3cb29a4d77c7b1ed6cb7b2c5ca1e83e058211bead3388afc0e250391d8e991f0a8ceda3048eb7d8235ffbd3076d07bf5b29718897c9e696c643d3bb9f705f7364cf5b25062ddb0d8460dd890d4d6cf53551c3f6775231e5d0d077b9babc91996ef6342a3f38c35d906aa65b468c52b30ce6efd7defe934ce0b7e55c147f75c7e00ec64e62e625ad8dd39ad9a871138a849a208269b1eb911fd7ab5ab2941a9508a576a391a1f5845bc5077ff59460ea5550e0824344c879009261a16f2ad63b2e918387b9ceb033818e38eb0fe1a89e708bd533f5d0267f8de57b216d9f11f90877c1ab1caf238a21b3a93ff3e4ae941c969077c2c74a9113e4766928bb9541b93c22c15906a2c6e2df0e8e19f3f9bb3bfd9313a081c6c1d72685ef8188b4871036c52fb881dcc73cf0712992a919e0343c7c14432be73c04cd829e01f36011c16e7a05772d516c745949e4096baa7e847db0906440757b07b9c9e1a118c4fb6cfe111aea6cff111934866e90487a0d53ea95489429fd995d05001239296dd5db381973317292ed575c5e83d148d38ff3cf4dd880948a182acff413fc9003944721d0eeba348b7575b869b7d71adb86dc1e71894e0a303bf7a9b2551d22973a8ec306173a14691b5646c69817883836218beff2bf883919c84f3ed1be6b27c33a08d102f0f22a827b540f3138d6ac3a5aba8fcf15f5741cd717e7153c68a6e18e2d6ea0861419a97272b250d1897f6bfbed5190155a0ad8252606a533c278a313f2f5b44500484bea18f942ddba59cb4049fb723ca9d36fe829fce0893cf0cd0376553284b5c19850c9e70a03eb6a1ced860371329299c5fbf5cbc830cde709545e6f3254689456628cbd21f6ede4d83b6500711fdb1c8c6b9e6c0b48425e7c458ced45b5ac6248a2c04619c7acb2f12dfb232ef9e278d819a8fb6cdfb2ac0e430bb3f933a3623b1a040c0c00719763107a6a3d98e4964eeab71957fb66cb93064e0a9faf2057f2e1b8a83408cb4dcfe6e8baaf8f3009783b71b9aa7de947db926daa21347e4c9079d0a4dd34c4d9c6448dddf7445e908d8874199a16787c06aa3c4a46910a5c100927d44e671f4220e0c55b6ce2f170c00cfac029c769c52a1f7df00312a8784f1cfa181d8420a237147737fa138c5882b42438f4811943728574777f8a30615832502aafaa821cf946ffc6cb9e4898ff0c635d9ad334ddffaeb7ab0efa60f6f3ab3f5ff5a33c570a0b40c048c32b8007affa7c6504016f7084245c1710b2c98e900141e4fab3cd24687239a1d37e17cb8f1a5eb74e8f48fe4459643ac3c689e7d417872c024bfe0131f33a08608bf9c1bc501fac9b87b429fbd311b1644ad82dfc51ff0fa58c17fbaba745ddb9d484ed4b83586e6e12603eef5d992d5f8fa568d19073b57e0439f4f17baaabd0fc5d32f01c53e9d91567ffb7b356f8db253ab3d17a771f04a1db8019c47eab09bfb772c71719f8c55e55eb19a96dee67cde2e03ae68d44c8cda89c74b955f50959bfb154696a6ecc7e980ab2e71ee2c1f81eb961badbe8f1ad111717ade6204b1a05f3da310358b07de28861bc20485fc0448907b93865a78cf60d71872322606794bb3f510d71e8615067c7ab10f1081ebaa532536084c1f28bb59f21f6540ca111d60186ff3cfa074027ae0455666a6c8a7db1d2e13dacb66fc34e44fcd9b88b6cfedd5c0f40eee292c6dc5750e339e6951107aaf7d088a4db46efda554cdda905945904277e847b21c61ad58d23016b2cffae37c71d73e0fc225ea83892a0b85b26e3e03622731c6f6ac1edd104ed9d21fb1e165cb79c99844621777e5b4abd674c5d49a718ef497811104974ae50f6edfe8f69633712187f665b73cfc923974238345737958de68267b402cac8b84bde75c37da368e0ed16f2f3385cbc7ef9bb0c16d33a54dc084daf4ab0629621dbcf0af1fbf7559fbc38fd7be85d9c6edb840ebaf11e6092d140226be5a0e469e7904f34c5f906bbd8b7907eb4fae2c5d691a602d6be74e86e51cceb9153e13bfa31ef4b7a1ee498dc0a8829c6ca3df32194b5a3126492755520f3ecce0eab42987157d4f7d425f57627c6fe85e8bed6f012eb7bba74a5b3dc8d668f0f38d3b56f418062e7143b3e38168e859003c352bc31294a2f1c4fc3ac0985ae9c3f9d245c4edaa500c0cb4d021a720e66a07479632cf8869b74753e9a7bf6fa9515f409a1d1835a02b3efb3c9b32210a636544b24489974558d27b1e81d333fa774c0f2720fb5f94cd6012a4c15fb15e16fb6bdebc07fb490d65a5fbf936a5102a895c65a5b26a0175bd2d656dbc953fcca0138c81515f251b9fa81332311309d6f85d81d21e1727531b52f4fde3ab97cc173f27f38db5663f980e3298300aea043a8b280ad4b67d954b082da0157f44db4648c94f9ae8e54446f6aeed12caca2837192bc1de789ce164692be38bce4eb79ddf8dba56333419ee4c0a716e053f2f00a18015513c85329f1a0b02b5ab488d9f336ab095819e03fed8cad9e8c13fd1f0bcff4b68cfb774008843f6afbd91315c151e92022ae1e3c9363878cfad9c96d54d35ac7b9382117d159546b14071f8454ff106b69462cade938a725802ccf566eae1c75020e9480295288c0450aac00a0d129e6b106b5c8a6d3456d78c594fd225711bbdc68615f59d845b44d412b95482976fa2298b070d5520d2fdcd09571d28d316f12df5a325507ec032989d9e4af2484bad7112abd13c79a3eb40197000d357f9341d3e4c3db4a73fe93f47fddc617e44ea3a769aa57046fbe1771a9a7ee11ccb7c2562163a8a1d5ce2ef672e76bf1c86b1e88f064f65591e7a4aea92ee52b2f6be6e633cc0c114a7bf9b15a44838f1a1da333a47eba09cdaf4baae0db433cfa0b939d8483477df9ebebddf43896d5b1336632c89e90b3c9842f59c0247c5b21b0a9d713e0427e381f5ccf0a966bdbb272fca346f32a817e55682cdd486bdc43ae88a62ea7a603b5f14164000fd67c584f9a8a1410507441db55b7f94512d0d432d0b12ce0d2dfc44a7f5d9151e2b2f7223dd0bd8300e694a054579e057de499016483324348a8a9078f26acc666373a279d787036ebdd99eb89d3070049869af47501bdd5dad4f6cc75b47d966318850eaeb40e0fc275db2d8471fc9e4f32892d1140173faac64143cd7150f53d052c0c33119a860d45afdcde02712fa3c817d225cdf6aa6fd2ce39178c90359dd32d008a1568043ab9cea0decb071b9568776e9d8fffdb638ba6ba40faca60ceb36920c9aa31b82974a8959929e712dec327e1460df9c16943ea074c4a13993c011f3e50b4d2720cc2bda1f6715054e36e75710628bae06356855fc6ced18771b9f051c4af12dbb4f386518942a91abccbd5fc8cef9c59c1bd5b361d013e33d00de3e7d4c148639d98ee5085836d24f99c880437aa7ab200e3ac4ce4347db58a2d660cc6b2105d4addd16a7a65823d625e398c4049aa3a2ba0bfec075046982d28e910987f844a1386ea2f90f904565cb6f1bbab21cdb599aee40557cebe1a1a1cba28e93e0f1c060f771c2d263447c4428ec7831badaa519bfe1facc3a8b6eb0a0d1151ef839bb3c43197c197dc3667fd443e62b376fd625b771188bd42532f41b90b885a8cc786e1bdcb8ec328d39c6e56e00ba59b998e838ecbf2557e0061101d29a035778e149b79d680b010789981c52fef99e35080d0700fbd4ebc803e6838f29eb4e78754d78a7220d9dfa0cdb676013093a37072ed8305f56dc0509da371a5a9f977292204f4c10b28bbc90abb6d5def5a054d8c3189b3467e1d36f8cd0850dc4920701a65d72c5eb528b459351957127cf0c9a4985a477c0ac25fa1251e61bc22fa1cddc5b2116908112ac2701d697526fa0c7dd863aec6da0359d82765a11cbe240a5bc30da726c6c9df916b03d419fffdabf47a23ea0b07a7d40fbce3ae92b601fefd147ab9732a464c3c7a1a324604a1360c436fc43079787a89496a7996745a9c82696c4312546e98301fd0be3b535b5d0bc977a9f339de5673013d7ead5e0169ba118327e9174bf4a339226c3330837e277548d4876166afd38b22ac25e445bd4e038ec1863a7fce351d99668ffc96119461e12dedd747f59956be7d90551599cb849486875ddf9a2f69b9b4d3806209f2778ddd369d383166309b579dfb308a67d412506896fcd8cb6ad9e0e8887572da10c1b03272271bef86440aa7f162e19dd08afb03f80b2aa93c95717de75a444c4d2928e7969f07cda9780e713038e4c84003b66f5280a4e74198d34cf741906eac3d30e1ceb360ffbdeb2f60e9d3fb17c045b12e0541dfe18522ac08392e62acb6d80855df53591795a798490648993396f2e6c6452455618b0492f867d5abe79a6ea06d14e474c5ae45287bbdd0c0bfa8af29f5c129e06bf3c9ea9749689f13585fdcbfee8344ea4bf0f907aee93a8d795b4cbfd9f0472771360da3b9f459c6e36650b115d7a9b7bb7c8bcb321639e92b59d7d1543a865f3cf9d89ff7a2d6234b180ad67006f81102c81dc223190623504dab2867a867cc4317053a2059765ddf8acdd07d56fb426e864ab2c251157279925840886053991525d2d879e9412464505604bd0b06d49323d2c61559b6a0ec566288678e5e372d7272e367161f34ce3a2b38d7415c6d026e3afd485d45f91498d1e8998039efbf299c7a48fcd40a8147b9781009b3a323a8d9d48c9251dee5a0705ccaab123b6fe95b1b746aae00bdb6f08c665ce52da089fc51696eb95a9967cc4551268daa4c25515fc0be8baa0585ff8ad0bb890c51ba75cf4bbff2fdedb85d2bae8152e4cd74562b8a0bb2ddc5506fabe185a17bcc285e9ba480c1774f785bbba40df1743eb8257b8305d1711435eec8383092ca017eccac27ac808ad0b5a71e17a5f20a68bb9db161ec177fa76f02fd4f58bee7561342e626d1641d558c56af71749275d04393d91f30d171bcb85082f7bcfebcf3d9ea8306673ed9e495b89db752614d2573bb764dad88a2542344204239268cf437608e9bc9a2014435069fe15879d114001b37196492111303e6d5d4417604644cafad3eaeb3e75e4fba6601b21f8e8b652df4e38fb15ae39b0548c86993cf82f254e15805cf8c41b9975798f8dc8fdb9eea3136496d048033c847ed9d5bf212fb8a7d6c3c328d1de6c1625675332a28c3c2fb0a55136cf5d2b76da4b6bf63ff350c14d3e44f707326175495637b745c01a5c57ac51aebb52997da78f414d8874d5ea1e9bbd0a3e4f1a36df0e3872fc85654ee6e0cfdf002c1b75d883c409c9e85aeb44e549b5249f2287fb82539e3243025b9f70c51bf7a9baf93c3909a8a4e02987019a220d54a79fd2a457a46ae595720baee444d7e2ed5ac8345f3a808f913724f83c424d9b49c5a95d6874bcb7af00349f0dbf4e873b3eef330b47f84fc686c117846401216bd9b661f5ec8de7d5fe3f9341a3413d2416f9845a8840ce597cc533710fc998556c50d86245807b25eaa6d7ee46572a2141c6b8ae521aff302dc48bbdff0098791b4fe033e615ae22f663cec678ac16496b61023152cc3c0a46e619cf153a2b4b0c1b0d1f44111c8529c5dac42c360dc5d0c0e4c77625138ba858ae7fbb79d5aa9cbb33f3f630056a809d9ad6005ad3657549b4c4247997ef3d72b5c45704ef1713d09d7c85ed3b9ee5c3044868f9b4618791ba4c6b6ca0a5f65ece7a95dfebbd257641e5ec3971f320e4acb4ee12dfc01a1aa4cb77e5b050a7d6200cd87425398874041706c14e7b630e3aee60db939f2b355004afa8c53ae1551896df666efbe0b9cbe6c3dda3061a474ab133a8a2a1ac83526f7cbd4a3770c345106d2889b895e4525f2c004b2c68c656e29f5fbfb833acfe543591be6a33ef7ff2fdb9ead4a6bd4c9d2a7cb131d9016f9f46f979f2085e965883252f6966a5e6a4fa41aa8f23002e63906c14fd5286a186aaa6a642a2b819dd71973e4ec0de17795e85f73b45ff091c44f6adeeda66e0fbbe01329ddf45587db0ddb7061c7d670ec13f133061d4cd8808d3b0902a7bc891da82faa4a511ededc156ffac15811257b77f86f9e29462e59b6fae231d6b5b511772b9e6ba65c11e969584c3783bcc7ddeff2cc7e6f06553ce6530da90048b16b6e615ed08ba3ee85637355d1138021496bbd946581dc092350a79d7087461744f8eab463c8c9ba7a034d13fd5a1a42405ae5404ac8101cf3c8a80c0bb3468e53e7db3f072ea836240033b03dd7886914de378cc4d6d1669dcb35f8a215b79ffd2b1dcc3c29a430291680517b5a1f73b3040530cfee4b650095037c8e5f1d4f10de3257df082968282afee37a4f006a28d0fa9624ca8253d7e083a9d7876c22c429c0e652e88d9c86a5d94a1f54ea9f49ba08bf95004dd80e6f1afe086d5231794e022fdd18e3f3c1155765965e6fd99de72f68d7469caa3620d3605e06c0512cf60d1ed8b2b30ba22bee647d93174adbbb84e967dcc414b0c94d08a99a8ffc04a4c44f3651cf4fece613cbb326a1ffd04db6c000615a1f800b3ac81d058096246ad4a211881bd11a15ca8c9e0c781be74cd4020f4081e1305b105f16346d6ca95cfeca8e8a63ba80705470a492139ca90c3005b8c8a6e2c0c5218a61682e443c1564ae0c7b17eefbcb1b4a82c52ede363cbcd2cc287550970833bcd597a510b3007236a0f3582923531f29cad75ce01045854b7aeba54adb8ca2745777d5056fea59b53023f36a771514bc2518e3a8f7cc6b3d23359644db8d11af8aec639f731808e0fca73d9e0829d1696f2a5c9fbb19701d76bfb9c7682e95b0d469123586288b1842c83823b2478509223930203c70b7c5b704d551e66fdea6ddd096e091b630874b3387c83f736b2518484be0f4df82d32c2a4c71abd0361070043c15c6120d84ef54e8f89470abc5c1110bb27d781c4f16b42a090307e601d00ad6a3012b87c5cdec65c3974eb64752f996f1e9c789d5d7c64c4c0ea2610605602245b21518a565b8d0d800979a35eb9342818d0bcf17c2bc0ea9b792d47c2ef40f48a63ce7b1b3a8a31c9c47a46b701121e5244d297d4746849e02fb7ba57c099a7ffc41eaea70d1e5f4bc40f70b70e97cf5a5dcfe1a3d67055e8d354dae42068dff0c8f459077e8b6e31aebeed69b38e3ebafd75596151d9165c7cabc48cd8b0c93f2c379409086d612be43290cf6d2c823cce0e5dff533d106e98deb8dc666b8bbd40461eb6e4abee130a2ed7a3b207e1907199fb56ae11fd2ce3ae58ab2b6bda6a47b59e475ec71804c1bc46f2c4c0b0d0c02dea7baa5d05b3a611657a5fbff7269ecd9bf54fd6cf794f0401e70280db60783e43feaded27f04f55de150410db8faf805cbc1ad787b4f6dd2cb0821f9c3f557c57eac3ebcffecf2fbfb5fc04fba9e6bbe21f7e7fb67f7ef5ade127e84f55df95fee8851f48460306c2f607df4f35df15fff0fbb3fdf3ab6f0d3f417faafa762b6dae66ea19e37b2e54a02b9c5bed80d240dc751641c09d9783136485a500a22864c8206867f178e211318730da5ba1bcaf775e460c9db596582d6bb6f046f200a74cac9712f29cdba6504e4d52349e2071f5da422b14f1d481b5d10f01bd42046bc5c058fe9a6840771d906424bbb363931b5d8f98bcaf4144f7c6e2378f933719bf616e0d48784e6ac59f7aa790146337878499f48014533a29da2639260e3dcb13f9a2deaf2798d7c5d44351f068f66fe85c51a914b4f33a5d3a4bed81b5f174ffeda4ac01f22472cc7853c82299bac792f7948cd5525d8190617d30c4db126b495036d3fc4fa5446873994c0bbebf446eb6222b777b7e2bf1d8edb2416738983d213af99a4d9b96118d8c418892338c938dedd5b5a0da5af2abcd4708e11d74e73687f6d140c1507cee90ede986852f674b500c4d05f9ff9e3c6aa323d7fa4a6d727e2c69c5b235ad5ad8d21637cf5292d32c88d056ea71d240ae416bff6a1c97b82b2d3d090d92401f5d290e2141958a2648175827906473aa404428acedfed02e2b4ec392954819d4bf45ae13cb41d3dfbf88dcc55c83df699b95a2e74f343c63f3422632bb8c552d62cd5e4c0db302cb7fb7cd593fde94141030e4dc31093e775fec2aaa2bce82d5ae9e9ba0a9d75a6c314b0c8f8a605affeafce1b3024e9bcd0314d3cfa5e7f115b39fb4f677d57ac171ef68b59e4be3f2cb67cc602e4c9c4d872590eaec7717dbcaecccac3b88bcba497a38a1bb18933f682ef5b9d37be821f04e1096a628e9e4ce0b023096ec61ebcb79786acbba2afee0002ac1a180148aa0e9193efe2304cf5e58710cd1b47d51e5b6973d9ed1a8266764b3e443c846d75c9dd61197c7afc36573e2fe69db4b0003a77069bb9dd4ba41ffd56349370646881cf75a5d9e8fe783ce940f9503011d7d278850a148e88360558164157ad8b40c0de09e397300f86749b49fc340d552de6a1ade937867ef9441b9b7cc5fd737dae48c6a720d7111818f865166c679f21bb4a31fad8f0049e8f568165257e34f89505f63b20b38c1967a10f1d35667b78a35b6de731ed74cab942789c5c416c079dc1bdf966908e54aad0de606b1974066bf0e56a3734478281e7d5d8f30daa0e801e55ef984c03cb69b27cd2af0f397255f3063199d63279a85bf9f37726c1e7120bc555e8105b410a42c8dbd600b901377d04613f797faff7ea8e12d348f70c19211cdf51d43d5cb0147e9940abec0c9408ca893ac68014adcaec54de740919775412f22c136c3454061b1d20b725e5515cc0707fa2210cb6069eff7f8e3133ff10b7143f642d10118e7b7840ffbd5c356828c7dec7943e82c89af4f828bfbc3ee487a36fa859c938af6899438daf8e8a4c7578fcb41797fa026ebbca4b5bffa9fcd0f9ca965df1cb4bacf60d1ec4024ce8293cc34b0a675cf4ec44a1b08de6d16155143064041c33dee2310156b45776cf0af818092cc67de9ddafcab8f997ade22d2e54c8b5de20f989be9ecdbc22ab7207dd98cc604da26ac77a4406c4a53816cb6384fbe414333dc6c16c84ce33cf46b4fc9002b75550bbfc638c1716012bd571801e5daa5f99decceaea4c44ccbbd2f997c10e0ae1fd46aca669a255b0001cf750434ae733085c11d9e5e7401f2ec308b47d8820facefceeac2a9e6cd4257b81f8b1af906e914bafc62a8c96c084cce44ee62a06c9235f85fa0b48b3e419094d7d62ffe01de7e2f7d0bb0a0940185c7045d9b12be452c53174076668c1a02a468ee454d911798bba0db597343880557511d9dbe9d8698fb5cd70ef91275e9e8f9cdbd1b1fc19c10fb8cd4f26b062aa4d61b6d30662566ddfde1775bc1ede7781da3a3d271c015d1629f23b1449013b9b11a0cc1f5ff453ca569738429a47fac910394c6bd1ad8362f1728df2689a457140127b7036beaa58f4530cd9bd330e72575c2f112c17a071e375f72bc81036c185b19a6ffd6eca105ac447959caeaf1e5d14859d1ce1d2f7ffe820b287f25a45346054aa7a96e136885062ca5a39865317d34858c1bfe873715552280a0f1f0d9bde0d467df5fdc2ec65338a9f31d1b0c395a64ee27a5e3314449a0c210353d9a7273ad6e1aa16607a15a3ee632b85fa407d62d01d7fdef45ee285ec02b0952c41ba4126e3c21d63eb16096307d95473f214b8f0b405761228f2b75992b59a9a53ebf7502533006eae2b72c0a2e3e645de135f8a77724672c5798a52139fdcc28479b5fb486deb82d0897578eec212b50adb2deb7f6a202f147359c70f5af9f5bc141a54f69bda01436c240dd6d666007c4f47d38ff912b6af3bfa087e494abdc461601a440b5fb154c2b3eccd38eb8b1d2fcc408be04d855e685f40e1afd53e137deb8c4bcbcfaa71541f7452fc596b595c6c576b43ccf09121737d3ea54a7f138113d1ba317677a8f1df6a91b38d81d82ffa3f9fddf42f980298c930c0894666f9e73ef89b6c503d46f39df5944baa4224aa498269d1b31dce11302b5dd7119c2b9817bd86e4a018f036c8d6cf4a75ddb4bfad3afae021c71344b99e1c74441c4377950c7061e601d4efdc60cdfae67461a578fdb29221df53215e9d5427c6efd3b588a8564f114cbb26f7bfdd434cbf1de30dce21686da15df2910244d96be42cf9002b4b0f28e4d295a9543d47487cf27111c6014eeafca61956d1c6167170851db69b7af7a6b581f27ec50d65f5ca8a2f2e969ebf906591b3165f5150b4ae32adb3d1a255d40801ac30008f8efb0559d516f56800f1c4fa080da66ba9ec35a0b57eaf39c1297efb117ab58bb5e24a5a913e5ab7a457e9c48106ebd46d8b1e1ae3c4cfcf9aa35befb50437b327938bf8025e156d20d82f92d7cc5dacf12a8bc4c3d8aa54376821a5e60228e44df0724b253a642addb17d14e9b37f7574a80e12a767558503c868ae3d6315d1b516f8f7c4a4a13002eb4dcd9ec646addaf6f4bc5d6dbf1ed206420cc17aa3ed63c1ffa57788883029224120ce80822386690147d4999ffaa46561b028d296b69cd9b8191b723d543c7e00eeba2763f42a503607bd33f6983e4591e3f7c6d2ac4c3859ab84c8319aa88821c1cec2631da0d1a5d2df4914021dc92d94656ca4fd68e8f11729231cd334589500f3239b862d66edb119cfd98a78a85deced761767122946346ccb6d14f370e4ccea701c56c9e16265d0c5249b341192ac0e118a811b0f34c8fc59c208bd1ee713de7f79f59254772ba5a1bca2efb7e68d1d8d24b78bb6a54d093acbc58e2ad5090cc48da8374cfb9db8458ff5709b180a21870a1c5b7d7bea24b841823ae9a88f5749fb68c1f5fb3cf4612394721988d5533361ea9029ec640681d242fb17051d4a35380a8de7c8dd84d76b04eb106874320c73d4dc8aeb4014e84018b84f273d778b06e9ce3fe88f0508f0bf483ec8ff1b1982f618913d1191b4df06e937a2108b8b3fbd6787f35d69d96a756c3353812b33045b51de6199c86524bc63dd6854022f0ff244f598d6841cd93caddc650a7c1662be7d0600f40aa1f01f62439e93821ba4ba699136b4583fead85397009f43f2da1e4e457d0272c3ee57fbe11392e858dadef7dfd325adffd8a603c8dd274c78b575668415f2dfcc79886497202dfa694f549ae599f9120eb4da9435d9d74632c8879b8bfe9e41184de3dd27f16e4579d4e19125a075d33d4fbc0f00275b32c94f2746466820b145b42f02107dd95e6b1708a64782beccb7e566915de8fd8754b2913b6fd2e2c0b31dcfe258094a82bf6d6d65ef1447827973eb2d807b40c6ff698d4085cc3797bb7906ff481da3bcbd7571fe7809a5d22cdd54212785b25e98defedeba85241fdd18d75b384e776d3ec30eadbfd2b29685023589264cc1a3e9a84b8d683288d606813b672f37db4053345ac02a7d303bb732ba53e9bf9bded254435ea6927f46dda268b6c2158bdfdece5f70e0a46491efb3b1230162d2a3d67542c65a27f80a60edd07b4d342123c3afd983e96ea872c500264fa7f2f4cbd0bef2c3aaf0806808f05e3316e550e6cc9ba51c288a225a38d66aaed65593025827e616f15f3cf3924923e2d296eb1419948983275ec85c0888d92c0876f6076adaee6add28659e93064c88057f201bd6f7151901cb8087892a1af683be0472489350cbfab18c3cca376efda37714e6f40ae4bdb43d01d76b194b52ad31cd91babfaa374ef36dfae10066b509c6215a4b51813825f86f418bb67ea3b424680663f0f76925b3a105c1da5883a64d04f8c5f77c907a30aeb834edd3ca20d6eb46b6b1062be85eccff8e515f0f61d19a061f34c422fd653186ce29257afff671688ba7fc749dfe6e6918826454c6806e947e8321ecbed087cb2055eb6ecf296ddb8c1c63f45d420081edbf67fabbecdfb90c54ae28b508bb5e35bd0c2e3232a2bd38fcaa880b5a9e15e63395e957d1fff0fa6cbf1e0cc4458ad933c71ae0e120528e9450adbb0f393499bf989cae2f9c92d0b574e50f312d0915643cf4606a1969626ba63c15f09e897eaf2992a46501021f8deb7be45f33ea684010aeee3734b5a87ffb30ac130769fd894d4a62753d92e3b9651cd5b265be4815f778a9a25d370c70410d4f260a95d4cfadb587c19e62d7358cd891bc25c41469b25ea8a63239470133aba6c4818e650dda428e186f715a7ad6c7ddd4261c1bb0b9a3f6d81779cf0e52f5d5c3f80a529922cd37e030e3a74db4111459e5d387a4f69e90acd92912e9b0ce805686ddce97cbb7a5a4f7095a9c7133894072b72a54d7702ce0d44b90a3120b4a4d001c0300cc3300cac326c234ddbd6e8d188952949c93ee038ebc46de324a52d534a696d63c6e036420821e4a378700a950a490a6aacd163871b3e7ec440c4177f163dc7bcd9cdd9f65e1c9a4b3dee4495cb252f761b9d3f7bd3b36c6215ef61061b22bb488f8b39ac6f958ca2e9424d515af4945424170b56253f9d8b2da6a57191a6d55151bfd17365b7e8afd2734c1adae2d86296c44c89f89c656b51092dcd0b5a2e25bf545ad852fc5b6cb6a8c8cd2c6a2f8fb34128d5520bcb023d2166bdd372468c0597f93193ccd43108171668c5cba9d66517c647afa8fa54bee8ba2c96f73f5260868e2022ae48c91fa127c534cd3c445a81786b9ac6bfba2c1c0311569c6cc7c5f9d494f2f92a503a5dc7474d5574d2c50b6d326886a75271abc9765f17e5e5fe201f440622a840feb45d764ddb7496532432c7ed53bda645990d22a6f8f46c8b59b23e1f83444a9107e57144c8e64d23aba0a0a4a80104f42a2760438414751032bc68cbdfb11b0639d4d001e47bc0600d91512c5678ceffed85ba5165c75199818e1f3058d961021494951de70722a250ff7fa458c57fd2a5ca8b84227d4288bfc82ccbc146502ce7ee0b97e1ece4693e819ecc353a3dc6634e40443c91f61c3acb66b113c81bd35c6a7b838adfc74a4a1b417cfc58438413f5ef9eb65b5f64138fd07c61a2839a30e78f25343e66cc26cec4d2e6caf8cba24bef59306196cac9a464b71c8b5c42dbf6b1f76cdbb298882514793a8a8bd9bb6fb6248854e2b872eeb2c8b059d347094f4f33bfe81ee2ef491ca6b6f647a9da116a4920466831f4e8244b581689c4c591497bfa20d1bab7ca8858be2cc91f710eb23f0b32f38e684de3fb3f9e8a57488748234cfeea5934be5eda83106144b7ffbad14ea498ac5450504416a1cbae7f1b7be503240508fd3f4e8a28023519f466697551e35469a35f4524118e8f4adde0b2a454933adef8d13c7804494304116de8f822b71f6af7211232fac971cff1d49b8821167490ddeff4774fa7359a0d15d840a4100713bb55f5926d9ed6e1021142a8f3a3756c94381b7510ccf6ba3c2e469917d482c8348cd0d51736323e100944993989bb8ec7542f4500c1f967d6a47eb6ba5cc37f8d1fcfc345fee0bde4223d66df24a303113fb83fa7c58fb6aa9daf3e6cdafaf3e78afdbfcb07ed374fdcf685292514d9c3619ba458c849eb38d203e2b13e73e66c2db946240f6ecc17d37fcf7099c543b5a6e4e7f0280e44ee5096ecb5708b6fb13495ffc1c6693584d03340411142ff2881881d16ae46dfe81c6a456f1288d461d96350ef0fb50a8a081d7c7bed8c499bae0b8f4f43640ecb212fc707b1163e451b88c8217d293c898a77cd12a79f411c1223dd5a92f78bc0a197e3872dfff8f3e059d9610223f20683d078d3d5116e1f97418e33742c226ee8dc73d29bc15bcefd042cd286f45e6acea0b408312d0c44d8e0cf8f8c722f88a6bd5450506020b2864bd88b30999e881a8ef5b278f2ea4577da32104983db5fa583bcba66ea55527ef88881081a3c31a127e4b5e53aa58e17889cc174c9fae55f903164ce0c6da7d590dd9299f40b881b2265b852fb3f95163550508e6740840cc8cd82ce92aa94d7f7d2c8b12263e05a5e2c070b749800056ae450810b72b040c70c44c4b0e7962c3d29a5e605934a1969f0f0e13d7a063710090322cd5afaacbf679a45040ca98d513e75ab291b2d5f28fb83ce1b19553a965ee04ae3e6d7d3d362ce0d43a40b5cfab96c4263c7a033225c685c4cbdfe7a27d39a0a0a8ac81696ad35cbe3626879d2f3d8a10204046e14a1082c10d1c2a785d5bd0c1d19c4ae52c62e44b2b0698d50e66bbae3898532c9a917a408cdaeb0b7fbe6bf8b5640dcc86b0c26caaf3a225558644b7dee0d26f4c9bc00092254d075b4a8d579bfff4c9129a45df46bab9aaf4b9388143a0d6a839c91d32fbd48147e31f35ce924eed24b4241040ad9bc2ce78a58092bd10d9127a01935c3856d7931bb38213f213a6f3099e1924c08224d3057c8742a5eecef4f112654f655253ef62598c3c9f0e8b2945eba1551c2f19470c946464910928cbc4d684ebf15324cd1c1a596f63cc69268bf58ba285a37268a1063a06561c38b966aaeb7d4444831b0d8b3eca89e278410a38c9e4c962edd98f345879061ac7ba2c74e6c3885a1f967134f61df9b6321c1d046cd7438fda52f6601c6b2fc6b1459a641e86018427ec16ba6d816b6745b67437cc107d971346ef567325510d28b841ce5c25c0bc24fbc2021bc68839d9ad0b1b32f864310b28b54e4c70effca78cd87e8e26e49783cb32a17e8bef4b2072584f6e8577e8d105c2c0b4a0b5ef79d840755c82df494724af6ae494d882dd8175f90e1f9927932555050bc47a784d402258488c6f10ad5a71c0ea1453aa716e793946dd99059203fd67a93cce13de87610228b6554e8e082cecb2fe684c402d9e93f474368d9c92a360881456ff7b5310b7a8368f715b88a168d3f9764c79c2bee585ae2267a764c6d05172ee2f344c966b16485a9af57b6258dd14dafc21a17f7fe36c84e9fa90233f5fcd2b0e26b4aa978d4280dcfcdae97172a966ab3187a93f4963b778a4d88fb607795f531a6f05c7a69afdfb447af434a81281db7aabfc283ce4348d1950ce639f6fb7fd2d22364149ea68a51a61d51244e9be89fcc51e583a1586af164182d48516a6b0828d86add2c32b4185ad4423ed1ace6effa967576174f98a9df7b944b48273269e992121e2c4bcf219c787ddeff6f7e6426396413e5d9f96691962ec8708826165d5042f5fafcd6e44c209396dc4645cb1d26fedaf8422ef16edc543a29ad2fd5176289d3ed6bb3bad479ba135289478b673153efbb9c5a28a1668d59f1d2d9a952864c2297ee6e55466d9c4b25a1e81075b359ccdb7a47a24da5e9bb3ba8164da80a12b9db95aed7d8300f570921e4117dbc53eba351f773fd468823f8b4b9ecb3d46be592778d383f752a193c3553653346a0fb93ae6e49778dad558b387facb7fffdd47c50882296e645d9645e17dfa544b0417b7c8c527af3e8218848f39bda52da7c2fe69043b46df539fdb370e3a510432ca92f0f42b39c904228e25eaa0db7a7254d4308b12c568c7510d25fac6e107670696414adf8e4e110412423eb3db3684d1fa19040d8f29bfa837e395b1a01d165b795c54b5a2eae3f1cefc35fbffcf9d244217e58c6e3addbe6217d38db523b34ef495167081ff4ca7b93221a5dec33640f8817b378a63accbac5217a582eb324947bbee0f685e4a156f3f07a2bf9a3da103cac66ee79eba93bb0693dbfb32c3e9b8442ecb0c7855d5668b9538842eac05d6c1cfdf51deec584d021aff1dba0592af5d70999831d5e4a76dc370b4d881c1aa99dd2ce747c939f9038e867ba76445653cfc70b2170b87d5bca709a3b29a987bc218f71326cf00d7111d9f0e1e3e85041881b92de415cbd180f69c3e27d8c7e2d47172d5b851036a47e42951ced396d660db92064b5c7fca76a5d881a5e91df51aa0949832ba7fbe782e6a063060db99c125a4cefc6b543ce70122de9f0e12263d2beb720471642cc806fcecd255eee4b8642cab0ac28ab3af93999b61032d8da314b2ebb2c6b4a17320643af3ce32875cf1f1322063ccfbd864bf74197191286c5d1825cc8ec16d46442c09012b5bfdcf4151fcb902ff8321bc7fb5c36971fe2855e2c5535cf0ffbab8674c1b41a4447f72aad4915c205c63bebcb39fee3694cc816165cfc2066dcc3da16a2854aa919e9a2dd07f543b25009f1593ef5e7ff2885606149c65fb2cff792563de40a188b97e2ceb5755a73270dea49030929b8974b99b672c1adda204146e18712f23454c6a89b82908822e963a2bd7e0d0567e2a2c9d5913bbf9180e217c46f33f3af06924fa86366e7af1e8927166478166f45d5892d83c6203c74fa40c2893b8597965b0e61a3637220d984dd5275caeace2a696a02d5a47a572f274f697320c9c49b94cb27f2b3974a8f0d2498d8f3efb4a938a144967a20b944a6a136a75fa81933492cc1ba7f70f5eb1d757925ce99c49ab21056522c4a543fa75c6ced49185a383fefec4a22fd2ced9e507e24b4fffc2ffaaf680a31245aed7171b1f4ba77f488d7ff05996531cb2a4a890412472022ee64ccd0f2189d2490340219fdf3bc582f8cf8c577cde9c38c46db16f1a64c9be52c9da1ca3c028922fef97c3aefce4ba6c221902442f58d919ad54ae9871161d24efbf2dac9a0bfbf417208eeaad38bf9b2e5fb213144a5a3b9bc985f98b640480ad1c8ed8db3791d0fe20f12429cdf844e23f3bc4232884395b230717f2fd7aef478370471c998963e772e57459240fcaa61b45f5e989612207c0b9163327d7e062d7ff8e3bc3a79d77ea836c306d5ba91deb26990f4c1ebe89abe21736a417f03123ee0b5bafedba646cab707bbff6f456b467cf648f4e0f769d90f427ef49a07ac63bad80f110fbdf499cc7bcfbbb3e606c91d0ea39fe578a2cd5a944f6207e56647a6e72456749ca40e978dc7c96df9a9125f053a7aa549e8a09fa9fecdc16574bae7808e39981af5cce1352708891c0c5acea5dc5f1735db58208903b225fdb259d113af6981040ee812a6c45629195dab37f872c256b32c68e12d5504891bf69cd7ee9e611bceb9937f98119da61d123698f6c5cc6721b3c53cda80640d9f4ba2fd5c35b3bd2c6a28a36750d5a2f139b634dc41458b8dcad090a670795dd74be4ee2a2467f8aab41c6bab41e65c9941dd54425c7dd298e327290372dfe4c65c1e19725978f1838bf11890b97fb54c4f6258ccfca325179d34845018cc58fab27f3481e1aa9e7bb1aadee4f40546e637e962b855cda917ea4f7d376bb2e7daa50bafb6b9b5e89d5b8c9370e1d272bf795521cf3d5bb0e3cf8dee150fe792245af8df423d5d12553a6716caa4f47907122c74277378b67a5134cd2b9c4e0853afb1bd7309ad50d8e9526f2d68ecb8552856d45ef0ddf4a4e429905061315c9c89ce49b64749059229bcbedbf362b8dbfe121f48a4a07696dacfb9eeb2e8cd000f245148cba94c96d2fc23fe238102df75a14de7b092917d82e409c9d5129b315764a93810244e60a376ee0f1faf378a9a60f2b574e9d7e475529130614936af67a9c8783ad2f1244be8dd3e8d9968101ac4244ab832b4942dd867f34e5ad9c163c719395ea0e30823c9d0ca3c891ae9f1e3db116418935b6ecaf4f975b763a4d46712f2828c9196ed24ca42e9b59816e3fba4b67d55629c44b7be2c6f996cd70c435d7d0ddf37635a1f61a47d1bd3bfb8275235c1e893ee6c31cd874a7301c6495f525a525a5e2a0d7fbce7f8f13a467eb177d0a26e9b599a10fb82cda62f73a5f72275ab2e06d36db39d608417c7fc55eae57cf9ae0160c2c82ece78ba65f1b42e505a4dc7abf89eaf970b83bc72594ea1eb438e8430828b4367d0a9feb65c72d10d466e51697cced0fe53ebf20823b628b3a4e5cd9f54932ead0623b540bdbee50ab15119a185ee3f2ffd9796a6a6466651e6dbfdb4329e5ccaaf30220b843ab1f9ecf386168dc7482ccc632ebea0b3a0d9fb4f23871a721881852a7342798796ccaa16448d91571862ee1ed6af2afa5b63c4158eb518740c2ed88a744b7938ebba1aa10432851156a4450fd12643ba8a36c5a6c7df10f9e235a20a7407fdd1a385bdee720923a9284e745d5479e9930c1566cb32275c7e111bd7c82956b1f537f9f2882916f67e3d77ec9599b48c5e6914e8f0917a8c94a22aa545d574ca73cc22529c357d756597dae4bfca0c726414aaa80819d5252bf198198c88c2cef4ccfe49093da5ab31128a36e67f7aef760723a0c8c47eb44794f8ed5d2505480331e306239f40bfcfbcdede5ff6d4bb8f178c78c2b6d1c1e476cc45e9473ab1f4b2b7a4b3539ebe244ef039ebf9e8cc8772c1178c6ce2a8e32fa88ebff9eb1fd1c4ba758e6462b330a139897017df5261c108268cb164de5fbfd221373f728942e7cd79293b780e0d1b3e521e351b6dfc0f158c58025d4aaf5885cccd9f83c64825f8cf2fbfa80b1d7493c60b52462871d0e749bae4e175af348963ba6ed277e339676e4412899dceb9c3c7a4f18232786030070774f8580980184622c1a906313aa3e23a2e95168c402237fbd4a4436db67ef8487984a9a50c7ac42a3574ac7c1a2a409a053ce20874e98c9fccb3faa5a7a2037d0d50506ca411c9ff978466da53a23b2a28286d00e9b12305238c40da95eedaaad9f51895334616818edb20264c8cb7d829658c284213b50f39abf6d1d444301af679f7f182374610914c6aff59d2d5381a83829143a06ab773b89c61c68821743193f88fe341bf34a2a09491c60b7c30520853866b74e142e98f5b0505a50c3442884ddcc5fa844e1fed45050565072383c8c6d3c5a4b4fffd8e407ae8604410c760c2cbedfe73b64525e5053f460261b0cf29669d4167f14ac10820787173c6f9244b0b1eff433a4bfba2efdcc4e2f543bea6e2eaee691f73a830d2876ed346ebccda82ea181ffce07ffab288ebbefc0e46f6601242b6984a88bcbf558395203edee8339030a2072b458957db1d5f93ff8e1f6ae8580982860950f03b7ea87174a8319287bf63f8d82feaf3ec88075e90ebfe31cc5ae43c7207f4e4e65497eafcb9237630d49c4b1f6b3bbba4d7a1f90da125b559da7f3c17e43017acb4e00b237448bcad7ab78cefb873b8b494b9343fff96b11cd8d3a383923109b9218fc339aacfa9e696e5fd1c0eb67eeab2b49737e09ee1f1cb4a7a69f7c7abacec48c1881beedbb5149dc551fef2236d68e5a49787cf7c49c7a894f16bfc78345050cec8c1021d68840da8e8133fa7e48389780d8b69f69e557435a4f3627ee15c56d5d8aaa0a0f078363e25078f6723053a54d04a9b600668a0b10224e5070f1e36184983dbb759901f3668c03ceb5568142b5b5bc7caa7f14600ce3072064bf5ff6bdcb419ae9356264d2bc39268f9e8e6286a3b880ccb31f6c75cbd5f873e8643c3fefec6519f94500cffbe87d2d9fcacf1c3607f9c66cde89a5edc7af83043c78f0e18cd3c8c80a16b29b47f645232f582912f94229447d3cbd36ff18817eadecc72164faa939847bab0073d7573f9f49d908e70e1f3aca63d8b7b1ad9c25ba5acbab4f6456919d18267ffc145fb8de262970533aeee68f54aef55567c9800480a46b08086cd26dfcfa57a5153414119b942ab29a34ec960a17368c40a6b964da98c2821846f84912ad4a2edf448efe062d7235430a5c97573c945fb7047a660162d8bc1c5322d6975302205f4be986537db6b1ea10a0aca48141e7d49baa0fd1d81022e8569dfbca0a534469ed0b654a1ff378f386131d48b313b6da91869c2c2ccc7163cb9062d6829271861c2f721b21eb55404c2c8124e7a54632973115a8e990d4694f0fc6f985352e39aaa37104906babe9b639ce50211645c1dedccbce518ad2104e9941e881ce3525ad533c62c9dbb9c0a901d22c6c04dbeaae3e6242f765420528c3c28b5d92c59c4303e77e79edc076d890c6399af4da5a26553fa1511061fb56fc3baf8c6530ac62db630de75aac3d51301c6a1fbcdb216f9c51adf72cf7ace72a6ee3e7ae8f81d3f02a8dd2e1d57932691785e90f262e59ba8700e2690384be29a25b391399dc3e411d865b67997c5963fed268e6074c4ef6c53dc654141296365082900d2140062d208fdc593eb47f951fb27134664db694d936a0a35da22fa646eb2a255c4b174c698839223641226e2186a94b518ef8367b1209820e23ff958ab9e4f3bf52138931fb245994b0f2d35c8e12d78c3c410b5d8ab9dca2c9bb5bc114c0a71d2571ab37ca11f7627c4414d7b46d5d895b50d02a1a4b9766c68b97f3111c4a53bc9890de2e2f8e60d93409c3d9cdc9c4dc90410fb6729694ab9a459f21f105ad08df9d7255cd4f801f92ee93cb972ff7d1fd48dffa26841fd0b2ecf87f3e36c5a6d526f6b9aec6159635acdd86c3a77fe04133df852fdaf4be25a64dc4df2a07b2e79775ff5168487c52ca7099dd6a6e75277b0c50c4ff2faa50d2676507cbda5df99affa18933aa0d363123d4a5df55b67f030a183294e74e84f5aebef1b98cc01ddefcf94f57c3ac6e46006132dcc5f0dc4240e5ccb7f163cd8e71c3413381c62a2d24ece6fb05d439aaa8f5e8f8604133720967bb1de72586de936285f69b39ff4b3e939d2c8f1821c414cd8f02811eedf92cc9db51582c91a0cbbac0f9d19cdc43c081335a0ec3af53f6cd02dbefc40c34dd290be20326eef67a98b76f8a8810d4cd080d0e22dc82c066dca42933374dfd5a94b3c4b233c5130318319b438ba5545eb89ac0ce6e7d9b8419f7667d8840c9b1026ee46e6517dcb640ccb29d6c13ce527a1f3de82951ecfe309266240b9e6a793314f9c683109c3257d3badaf078654bb9a167c7fc6d5e50ba819d92c6659dc1f99f7822ec5ba7fcff98816d385ce5dceb6236adeb4a42a2eec317b29f5dc9ab3c88460b205bf47e9a7f5242d184f2853b69e46b57859d8e6a3766b0ee7e925b18078526f21b4872b17bec22ec6a9f10e23364cacf066cdfa1ec74c7e89ce4daa80fa1c35d5944bea6752a193a6254e5c72134d41dfd196bfd32385c54f5a4c97446d97cc9b4521314268916b1b1eff86c2ebe6828d361d76b1c913ce2f29f35ad1f6ecd709e810191e2fce07192a259834413dabfbfd2bcf22a60e4c98900b2344bd6fcc1278c9d2b6428850976313255c325fe754f2823eb5dd25430bd957fe6a9b1d6633646c5aa5a64d4c6387aaea1869b213696a53599769660c77de33d5bcd6ccec62b06739fb996551fb354809316ac942c552beff4b3c0c337952b557f62faa890825c260f432897bcb27b374114a82b19b76f9be3e2d1e9400c32c274f5532e74917cf8d925fd419e755326feac5d34b7c616ad768416cd6245bf5c2b996abb367919b466683125ed4529badc9e421b39a76718993b7f2ed3c1fde1a25baf0a551f5c25e4be6d7b220c70a72a820470a72a020c729c9055adece8c95d59a3bd33f528082d23fbe0417bf18bbbecb4ae79155c92df4fbf83daf724a892ddefad310bb8e9bc5ba16c72acd5f8b570725b4f82ede3c48512ad376b3c0da731c19ddd37c9465a199106b6b4aa97d6fa050128b5e5693f29e65ef371758f82f5d6ef04e5a7431756ef4a0e415acb9b9edc7397f3175c572d00e4da56a2bd4dcb13b2e97d80d9b15dd65698fd1cf45465e855a67b32144ad0a4b6629633e5e72d137a9f8ec3ceb6395cc1ade0e4a50817be9946fee9f6936a7b0366c5f746ad271465d620a3c097dcd1d5c6ed32da570c76333e76a6953eb3b4a48c18996cbb4e61a051f5f0cc2dc4a3bf32f8abca4bf245f2f93cb1b8a2f7458cb2d5a028af37d4ca193f8ffd1fb27ea9694b8ec997bc274e2524ba5b526c2a512259d60fee543c938a74fc68d28e104ba949ec6e94c0e46946c62b17cd4a8760c772317a144138d10dbf7992e9de69d09f4a70bfa7e3b88a87108259848ad53082de770f1129fa1e412bc657b9a76614b2c8db92c76105752365b29a9c4254779309ddbadc9a6449e5a521df6b3b82c589338ee64cb73a13d09af24f197d4d4928ff8d08c23e1b9dc7a68712f81443ab74bf19dd4c8b3f011b9244a752e3dd162524798f6c3bcc799c839bf11fe68d0e39d35c9ca8c11ccb8a85f0b2a59045284ec876f79e7b52386124568561d6b731663dc74229229c2748c69b55bd488c8fbf395b8542f2adf21d070c9ca5e8cf1362c31046294eecc2e961644db42e4359f3a5755da7e08718e9f7d9b794568c92583a87390e1736bd02fb78b200a75c9d3b3e779ff969240783ee3b5fbb2b7d980c03ac62072947cb2fdff60921bc48cec0e5a343423470e1d8328f1c36bd931bc9ddacd92be0fbe7fe8d7fb0e5a6c990fbb247c3dc65135cbec81cd3dfd9e2e06a5d563a3440fa8973c85c669cbf862f2d0a7fbb2111d1ef8b812fb62566917e33b1c3feb83ce1927ff3339b05062875754082daefe49bbd742491d5e0f33f54d19d692890e5edcc8163435869239ac3e3a09fdd6b6e9a5e4f0958adf8bda2563d0d1511207dc52673f68ed2c8907874689a6176bb30001f92879c3f20b42a8e7b73ea52e256eb08468be988c1f3eab94b4e11f1d4b089d6ae5cafe1236545a7efb38a7b4246aaea1d8cd902d9507f7dcd4807cb96f09cd5b597d491a907145096fd183aceb4ad0f0b709a9d93b6651d622a1e40cb666f9b436834c2fa972a440078f12332c423c9c92a376791965f0f8e143053f7cc400e58d952e29c3a194f818339daf9c2564d8e3087361ec0599c4583286454db50d2dcbe296ce5c2811c327f5b41c93657e758d0a0aca8fff31031494374a5012064473649e94973f2f951230d4b7a54a946e4abe90d0224b6bfeb8b2724a438917d0cd9f9409b9f1398d1ef9e86186922e1c3ebd4b654b7a6365871c4ab8d0b9b5b7641bc3865b57c086922db0225dde0ee256bf4f2b7428d182a332a9932f67f78da787922cd4253bfdbe3cad6749102558384507b3123db55172853e53a754ab0efd941538993b54f36b14d1c9209454e1db136133ae395e8a885042853bb66f1a1d2db76cd6148e9b36e385d9f42436452891822642bebe5842cb5bb0240aacdca731d51a28e02fc812fb234e4b9d0b52f2845eb4da0aab0b8fd50ca1c409e8db8ef9ee5c56d16c49137a59b765414cad84129530c120fc84670c7e72e42e5942a379fb2d676af1c57909254ad8db4de8658734cd51259024830d6277774d46fdd220e318b3df1511a25ace8f71ca6ed52f99638c5a1693a6174f267b0d1663512e2ae3f7ed525fc4b0be4369107dc1469624c3387aee98f7a5d364e59208e34a5dcffc77561bbc29900423bb38fb9cb4eb5b90a18104185df8c8f7a0fa84ae310d24bf5873146dd91daa76ff1be97f85c417da26dfd2223537cdda8b44bac7cbc95d54cb362f92afa265b9c53f6dcc2e102fc5e9d9a7a89d870e24ba783b86f2cc1cdfebc35c98f3aa05f9a6259d6c24c1c5c266931d6bcb5ba0a571d7acd1b2eb6cb12c666ef7a4c2564f2506925ad49a33475f9239c98c69818cb767f88af3d29f3190ccc296633611ff52e73e5d1669d5d4532e7fb2dc4f2c0eddb6911f74589caecf3c73ac91b6d62bccf925bb49082df7a95db1acfea1b7336dc562856ce99ca5d89c9b15e8dde0e2fefe7b2e791579ca603a32d3e61ea52aaaec984e5a6b965bb2e140928a4a679dbe98cb32660d15cbf69cacab8f794e14079253dc827c59f52cb5a4da41038929f0ccf24be2930c2f031d58ea03591fb8aba3000728f0061b2b2a6bece8f18102c119105806d00a90203f08108037ce074400b00224c80c0610805fa383acd1a3d938800080fc40000d00802907c0b18964fecf0b5695ca9e054141e1f13f52dcd8e1298ebe0d2067e0d0441b3c502670c78a1b3b1c13b863850d15209d9282001c97c01d2b3f5480b0919282001c965879209528000e4aa07e4da6cc2e774abe4964b2ea729610e639aa8a243439bd9f2d548d7ab9c31189c5527dcdbeaef3a46c03f1781e28283c7aec58f9613820813b56dc078f20292908c0f18877c3070f1ecfc300381c91d8676fd25be72557234e5142e385d612254a8c386e4cebce395ac7fe178196c7d3bc33c33f6a14917c915617daf6018e442c0b22fd376630df18c58188ef4f6d500d2274a7380ef1a9157f29a46588ba3aac9ea6171c854898cc9944fd3cecf368e020c4e6b218a3a85caabc98ca03a1d5c031083b9f674fa6a5ed328d43107966f0fcd15a54700402b9a132e37429081a3f7ea50541c0010854d7bf66496875b1d438fe70d87117356733655b70f8e1dbdab48f59c4cfb9d400471f7c597e3edde5cc3e2d38f89094133a2813f11e92c94a269dce059965d783e3d539ffe133bfc87940bf3c2263e6b0b372e121b967164a0b9b9f5fc371073e9e6c49e6e776382f94edfca670d4211b15edc2ace7b0d5c14187e6e4b459e679974e9d8399d493b7183970a69d4cf48868d81807ff7c4bbad8295f730587654955687649de5ce938de509b8e8ef5b89cf1b71f38dcf0decf5507cd5b72fb3620dbffb65f7ccfce83010e366cfff531464b327df6d6708cd0252ea489190dab01ebbb723921af5a4c99a541b5ced2de21d3dae88680030d6a7e7ff76651f309d919964444ddf67ece7d32c33f42937c41b3dd7eca90504a4e9dde86f2d1428635ace61c4234598f3d8674bfbcd71b77ab6428063e7088c171c1aab5d6b4b398f3c01186c3df084fa53e4bee2d6de000c37bf2ef3c3d8611bdbe8056d38256798f294683c30bbc56e5b5a8164d4d293d7cf44801b20305e50438ba80d226ab39dbafc8182a2ea0d24d96cbd2b564a959018e2da4aeb478eb727af524e4021c5ae8bf538ea76f4c5a097064e10fa54326993908173d2ce82d49cd519be73ac357f85e4b85c98e8c9c8f159a17775b7cdf6ab5b10a478dade133c74f9a3654d073bbaebff0671bdc29142a575fa5f3b2c88e430a07f5b2604aad7e66df5b80230aa69d9807a5d54ffb4b0f1f3fd20a7040c19ad3a55cf3cb3967ae8282f24020018e27589681008713d29e3ad3c46a874b251c4d48a7e65c1ae352fcf63898801a8f9bb3705abab20c1c4b58ccaca36d5434cea7fe2ac0a1047489d2265c6a3949c6396596cfc26eccbf2ec8303bf48a8b76a94c2d6ae8408d93636ce392bbec7bd8529e107c9c0005259d18633161a7c46327c5d8c499cff7eb8ffe283172198fd1c6dc5e6e338cfdd4674ecce596b213c62593d8cd22c4d6a8c64607e3dfcdbd12ea464997f613601cdcfe44a6ac527b975fa86974cca5f94ce9b92a27bec03ca7906fa2a3935e94195a64bcb24599c50bb7b418a7d326e52fa977918b2f9b7bccb2fe964a1798d0a905b5d9af359f5c7cead3a869414b8d96c585f91e73ce8cb16577f95bb4973bd25fd277a53327b6e0aee5d998745d46d79cd4e2d83fa57953f9a9f627b4c8334f4ee3090627b34059d9660e229b5fdca471220bb7830a17cde534c2f32927b15844b68f14ad932f292c3ccfdddc361edbe3e84e5ef1e6d1d7410b9aa7da0301e24325a5c70f139cb86271ebf59225b21ee25618e2742931e2928bcc8ac3bf20c34e8392cdbe1927ab488985f7c83e61bb27374e54e1798b2d9d0bdeb2f8cb492afa6dc133faea2927a8f0fcf35d3496c6583ac5dee29f2c37cd8929963b84bd1ce306c249298ebf499f6a6d3bed96148c1633d6667c9e6ff70727a348f8f986d9fe4e44c169e6cc6910a65d75289c9341073daa3e0145da4ce6ec6292ae23223776f8c927166fb544fbc94fdf391e9ee057eb36f4538eba782f279d503ed6ac6293fe98ae8282c2060aca4a8f1d34586387095050504e388165ca0be29270c136bb89053173ba5355861e888e129c68c20f79b7a26ba395269d64c2fced2f311bd264d64e30f15dcb592a4e6889fc4e2e91d02ddae9601fce4f45e3c41265cca4d7c3e93f5e05fde84fe38db6810f21a881822282934a309ede7134072d6dbca8a0a0ec00b263c74a903da18479c23b8fb4fbd4238d818e951d6cb491060aca8f951e9c4c822f973a6d98b78fd62792d8c049241e990b1ddbb6e4a90c12293bdaa0c0c923500f1f113871840d7ca8b18193469825b12dbf9afbd96518b181934598d32fbf7c3754c84625850d36ba8d7774a2881e7d860f354c7092081b50e00411293bda3043053e900fe4630614383944044e0ce176aae50977ddfab8109f29d38c17dba7bfe58410093819442af75ecad1b6b1dc3c1144f2e1e3070f3414701288950792b2a30d3316700288099cfce1fc134addfb3d4817433bd838416210002e9cf8c1ef18b5c2cd3f4b6847b791d286104efa00e48d0742054ef8b0a30d332a70b2073dd103064ef280e3040fcc7d16bb831d52561e705287941d6d98f1a74da080133a6ce0640e297b2207df91b2f2401a70120720bf63471b123881830a9056b1c0c91b2e70e2060e9cb40102276c58831ad2e02339e0040d67c871620637be4f638c0e61f149e9915278006921a4a4f85819c14919227042863168e0440c193809c3064ec060ee1cdb9d054fbe008402275e90c0491780fcf0b1d23e58c080132ea4ec68c30c1b54e0640b857f5e6d9056d572fc7bec383c7c201494344eb4b0c61aad86074eb28005e3fc736a3186b52ccd2757387d960c3676dabb2790132b50e0a40a0f38a1023ab98d2ce1e91e3e76d0e1640a292680c08914524e4ea2a0801328a4ddaac3ad54f9fb65869327a0749469d920194e9c80e3a4099979782b613a2735fd1a6bf860230504274c10395942a5f6a2a667d4d3f93d51429ab23cff64b6814932f0add85ca73264e4a6e57891cd8f61b68f1fcce4323106324bdea3c4d78eac96629c34d8a56e52234a6e26c4f834f746bf3c8741729491facf307a2e6084c9304e721d2363844e5a744c84f1e7781f79ffbb7ac960d4327ea37f738be7123096d44b661ea46d5c954d7e816cd3b63b250444e547ca1a69e44023871a3a6680061a28286798f882f14f1e3a9ff033ed62d28b53fffe34741cebd199f0c270613a4b4a646e69380e26bb48693d33f5561d53c432cec8c1021520cd821f30e89546410b72a891231826bad03a3cb87c7c39cb2ec82417a6138b1d5df99268d132ced061828be635264d3ffe1e3c377cfc68c3e41666eb9b8896d0c4169fe66c1fe4651076a60a0b4c6ae1cfcb2aca5ada9873b5c384166cc70e26f3d37950229359e0bbd779bb7ce47626b2d0a52e138fe14ba56f7460128bf3abdb47bdd25b5ec2e2cb73551d9db2b3ba159357243e426971e1364c5ce18a2cfbd231286885419fbc889e8d7a1b6960c20ab3f0f1b4a6859645644c56a1a829bf97973e66178f892aaccfa55a122f796d0699a402f99214211a1bfea551414179f4c3479282092abe93e69ba368d1fc722a2828292b39303905d62d9829f53997aa900a0a8a89291667d45c76cd9b41e923a58d205b302985794276d4070b75afdfc08414ed884ca574cc7bd3988c62319bdc24c3e9b4e7e22a26a240c764aabfdad2bc6326a1309697ea99684167fdf858e9d102219880c2d36de2392372cb3e934f98fef774f3c7389d2f134c3c7128b1f14266bd538d1a9874e28ed91c746e8af0d04c38811226ede5d1b3d25f9a6c42516762612a9372517320071a390cb00a134d98b14dab081d7f5ba314986442db8e9e85cfdef8d13d769860850711de10820e14986002d74090e675594ca757a1eb9b5ce217b64ea6ffcc92d0926f9c94951f3e80986162894ab587d6bce0b267d3a4127db7af690fb777aa45a54d28719ff83ebd70399bcef3607f984c626df334a536d878ce4ac2e0570a8c6ea874d29288240e8982e150201000806066af410083110830504c22934763b18848da961f14000142281e564626223a20181e1e0a06225158240e864281302810060608421408a23c0955d3008b007bdfe75a493f634cc47435f840b8b7f6559974034bd2370ad40e9886fdb287d08628d890f387f21c1eeb538babd9aa472cab19806dbcf70e5120839b6e9d61730883c60c38bdb67010f2c5fd80e2bae23b7d4941300eeac21cc3dd3816ef6cea91332c9809716c8d983fa1d2bb9e32443ad0df3eca71c9a4918a584033b9dd0aab616fe998283b780b9feae2505e9aa6738ae6ae2de707b3ef9b294b377afa573c28418cae6a545894f914ab89365f690e99e16ed2a3ddcce330bc1dd7fdf5c2ce2bfd8b6d2c06651c71789fad630c0fc3578959b321030bf9206f28bf1dc5e526f450b6b0f8f162b84adb0ae02753ad3a56f5c2d3cf60a6e94d2e4bc5ea7861267672b02ed43c0578f5a038e09dfae9c3c7dfc3cfcaa8694f8be7244d40593fb208f06f57c5e1711e846a02266b1437a99745dbb0f03e55de5d0682c6f4f95d60ac2a88bd101a3132309788546c1bac2e3d932f40890f9f7882f3f957ab7d95a0159c3be77bd594b2b2fdeee05df648eade3a1058353eaa6d93bce6e91c1bd0a599829b4f2433759c3dfccce4e4b520357a22eae414b6b98266acb015b9cdb9a16245703ba3696544c8b1df1f6a315bbd9fa240ce73a3e4dfbc832de0da539ceffd5aad86cb36161e8695d161216bbe041151b6896a510f0708054897aa5f9afe11a00a57669fb15714ccd95c40d590d369e7a072c7d0dacc7a9fa8d3692669a1a24da2def443083fd995fd0d436bac563409c601e9caac16d90144081bb6910860aa4ce294e32d5d5e54858a07d459cda25f2c6df7fb542f4749d45afa79649bc6c1e5748eb7e4e9c2ac68c82dcd83db20f3dd705306da7834c8aa431ef4b8857fc8a34111768d7919878f9fe6da9f28ab74ca048c6b381c1c4c3d7b5df220e60435c609adf5b70dc579e90f8b7800ed80623ed72b5215cae3ee999d150565ab8b128ee413f5c194dd592e3a3ecc978b283dfbf74c4bb9a9ca583c355293bb93d073566b8a5277de5cd0928e856d02fd46c85b70b5c14b2c841b771bf5184f3fc63de2b6b6a51bc31b67f5b28e40f832619fd01bc22f9f10847f1523dd0e14cf05047703baf4f65b013ca24d8c49cfeb7fbb0d9409c334f8acecd27f6e28653a964c6de71bdf865b334a3959904479a270009d519b89d078168a3b4a3a623e21a1e32ebe5b6c8de15a9278f403bed5b95701b232dfb2b1d1e9ccae8c4bd0b46599ec57db4407b203ba6a525ed58d005e8f3eb4690bd29376b1ad7b123519acbd9165a64f0c9006a2858ae7a911671123cf4433d13a2d678452c0dfae4e210d5c1720afdd2509c305a602a8f50e366380d8caf42678cae23b8c0f5fc0c72a46a70930e98acb0e0ad7577283050b28f4245d517db42463e00990b1aa50dfd9949e599c12ff4ff0cb3957179df58ca7f6d13a8c1c066f1a3f0a93e94bae6a7c28b8ba9f5bc8c8735fa3f9aa5050615caec34afdb62b245914d441bfd7fd170fb989741b69bfaf256f4613774147df6c198f3874a35f14c34c2b853f5591bb0a8091a1625ebc04cfd862a54730813e938252a41bc048a6d8c73486e0db66155fd3fc45a35448d1ab6bca7d4644e3cc789e776faecce4cf1f7a64bcdc2c602e50dafea779a22fe2c09c4731d22c7a9c5a1d322443a83ae2879b29139e09a5cb4c279503755fae9aa80d009c80804f9ee2ab87413c12aa9c0bec07062eaf28fa421e0ed04c41604102f3407d0bff8b14fe4b1ecc32a990059a321b42efed44dccee0c585db58e748f45b5ed6530d8df835eededcfad4cecdb0a073b394687fb9844a162391c1862df36b8838d250f1e26f062529cf93e5db26dd438ce57b80a2282cff1b6e40507c9dfbca8bccc13f896ed895f73817ab82259ec11a036de5cbd880f6ade98750da2aef86f4f8b1dbf9d9a06e09c00f8ff8ad54e71061b588d29d1de9cdbf0b79bfd1c3bbcce9c9478a232257c5a7ec5422d6c9734096de66c350b079e8269fe95e50d2f81098427aaf31264b6a59fbcbac052c4cf0ba91e71647476404122a6f76c536457efdde37a10622afbf3e1aea4d8c90ed056e74b4ade1c7b7277ae14adee93110ad117d8f4fbcd8ed07aa6a78362fc4061908b77ca5b5cbc55b6b235f3400008e36042901d00577976ee8ddf7ec2366ed92bacbd01108397fbaf420851de71d5d95922de9013619568b01c669b312ef7ca62e83abe0cbdd96d5762f355c162bca43c8569c664a28f8acee7623aa8ee900ebbfde81550ba46203725a7af9ef60ab93120af32acc4de704478859305cbf2cc345b5d873de93bd49904a3155af9be3eb75c2ad6e06eafdf498364e9302381e54f86d0c5da2ced795ac770372a0e573386e55758622db719cd37126699fe6605bb7e42d51434c2bd113a016fce9923fc67da1ef42981942b3c5de8bd6c75f001f3da19a48c351b1aaaf7b54aa46d506b9eec3756cf64f806368296c07b0a1d8cecd45eac502ddfa041d2d52f6e2ed143a0615cbe4ca625a88e8aaa49f3c792c75df0489f4d163547d97b4505e5a5d16e40a7988bdce1a0e5fb6bf3be19f8de255bd7586aee5c8a5fd78ef3760fd63941105da11da75a15596f5ed46ed3ad0700998565f0c59dc46ac5bdbb49c265c0ff0f5d9580ee5b39a320bddb3855efaafa387fcdde62dea530efa7167b6cb9aafa530ff7efe1ae86310673a25fab9da7e9dcf9b4f8506b33ba086cae32428d55dfa70a383931748b254fe78373d743be3d16deadcb7d62f769ebcaee716542add2001fb66ef5621dbe6bd51749cb649f4574e6d9df7b4018d0192cff0dda1af273f05611f2e5a892c7697a9ccb026ea27bb83d3bfcf4380da835a074da39cba52272b1504ccb009515834517b6ab44f3307b21859bbcf2f7566a62fc266d58e1e790b3f60defe2a4e9d665c8c51a7021b7d2492d7f75308e383a89a8a14143150ad59583a2fbead99c2ec9017f1776f2b2df97462f89679502038ea7bfb714a3e6428ab2a9efd8092273a1f2d6bda353b963fa425933fec6a4539d8e0bb8e304fdc1beb530117e6125f360c8020494fa567ec8d9989190cc3af87a0af91381b7df6fea7fc20dbb038daf1334da8e487a3583ce605ae5b51f1dfb094a5302868b1c6e32a5057571a35e81c23bef2ae520782178a25869dd0fc2cfa6c0dd3b46581252e2c17c07d1d73f09aa32d40a820e9be285a62f5f9c099a29a18c3dc6f1b7486f76eca0746ec82423eea93dd01a122106ca4d939843fc3e885b7f92e0553c78ab11547e58eac183b738e25769536aafcc0b0f4020e8ccdced0ea09522440b5725716c0360d0a04a93ff8a9205d80ada78ca52259d0086446fc2bbfb37692d2f606a08d2a6df20c70fd669784a35892c89e5af3649bbfacb7f76176dee32dd0156acbe6aa97cbb8d2a072b3ee3e4ddcfcbae3dae6a3f5372e6eee75198f988fd15c7cd9bbd8514d55c54658e299fddab0a9a11a3c82bdad31e7bb80eca3810d1d68b8f19a33366c7837c2c4a4409a9aa9c7e6ae7191c9dac98bd178287f4d43416cf53b899399822b38f190d48846682c2e1669867280c64dd4828ead646356d9ed755460f49f78e99550f02cbf7dfc5f2e1214e4689c7cc05a7ea4dc0f17f1936d65310907625eace748e6edb1586edf28f945ce64c58b6e32ef382bf510733d684b0f0b5301b942478548555615ba02cdd9c15869478426d3ceba590506990fce8d7d336bef9eb69481d38e6f5bb40166dd897e20bb592f4cfa74ad3689c142724c8e2779e8b6b17ae01721f9c9ee3dc0fc2b9bf0a44ba02cbf5b768283dd0837b811d8df1305954d97419d297bc29698e49d23b856e930f175160ed56dabd3943f941379bc56d233fa38d8e70a40c601a2da809d7655886dca927249122842de44f31c81a5e0bfe0a03a1c04a5b7ae6af5f5b2775ad4ef89f1e66821fdbb62c7f2975bc89f79423cc8368e1be7adde46d625ef16c1e14645e3d153566995b200eb33090dc536bed66dea8313175a51472d12040988ed41f76a47879d54900167777418e9b2b933ae8b7e0226c3ef8edb390aa8636e7b0715f4ebc8a58d204caa502b8d63b4c9c7a377cc0834d858f601054d7adbf873f1f57550e9a6777d8e47b9f5662ad523f6b04810e73b7dddd0b7df409a33674385eac3f91c1cf0baf6edbb93535d813cfe5ccc9720a73c825157a6258c44a718045a793bfce5c4af70fd042ebbc1245ecab82b6d5a9629a561e1738158791744725ea0df77cfab367ec116e583e82dd0d81b8c15500dbbcd92d912ab1c4f803ca21c0b4266e9b49f016748b4ee88bea6962c1163ccc8ccba05e8040fd0ee10716be976d1e908fd882a3b69e20b7749dfb8c8e95887041d8a735becb931235d8df3d1c52d66bfc12a76da1a6ffee21150f1afaa58cd64fe8bc46d3c845548834aea8d6d1fea2fe005d727fde5be77e141e8a1da595f452b6bfc9011a6b6ffbb0f20c4bb4f584d8060a8a1463aa9d3c1f3f9f1165518eca4ff1a58cd2bdab833889bee388b41b55c5dbdd567fee530702a4a2170a7ec2e3ddd41b24aef971c1f4a02afd23f8fca67117e16faff85c9b885ba0ebfe1b34f5604a744b0d7e7c0f9129d2c673664353eb0b06cac30f903384ffcfef1c61aa65c2c8746d9b314706eb227023bb32719e6dcb5e44adcdbbecb530f22ceedc274715abf068e5fb3cbe78a81b9706167e39189fa62acf68b450d12860147b76efcd202a12c5f0f32fdcb2f3434add17692ffd33da4556425a9b853f467fc14a9f469cdd84233ebeac54aaa633e29813ed648959e88132d6a21427e3e3b87fde459196825d8e30bf466bf19c15d568c71879ea3d94b99b287b95c626c7e24887a2a4faa68384588a7d69534f3120c1ad10dc94446a89fd8624906a4a0f5c97c9ebb93823c544c8fa7abc4e2690c11632f0fd419ad6ec350e4323b04390d64e5434ef12d4102d43a821d7a0dcc3d08c854d8d19c906a407fdd0b167450baddbc17e9e6803efcb0ad79ff720ae483acb07cb3251670b00f9131f0478ca52cd6d4987ee156962b598af173a7cc61a864b224de89a19ec10600e5d50b0944a0b7aacf5d32ad3827b14a063d97a63d0cc0801c7c6a412192a027229b1801eaa6c113d937df458d1d5e89f510bef4dff56810d6dfb16eb5ca4bd6ec8813b98972d40d97e063d8587220cde87584e794803ad81d2404b4043f582bef2788b16bd1866f2bc083a4e2e44eb87c1455fe50b0414d2a2e81244f8ea43c7da8576384127a5f14a148c73a08f17ed11ec109cdd05c038c14bcdbe309f5e5ef130ead749ef6e80238ac3e64f728cbf18899da4df77437571e2dbbc795318ca4752cada54654409533232374504b10061992ac7fd261f5a7a12c6ba06dbede0db71da832d3baeb86a5b8acb42c462959edb6a7a07aeace2d48ac0b74ad00098cb5e24d48b7b56ba8d3243a8fc752a410761d89abd81e6174079fb424b32cf2bd387a8f3b201ae435fafc5fcc9001bc5be6a5c4c080978bb05792b13bae03a0973fc7c5d4ff23404a0ea7f42b32fed731233110f42a876678a34980491d4727692221f6b47853266ed7b885baaab1749ca069f4954ed8ef84d074c4b7aef4926aa108e91521ef8d111982b1148cdd632d0740147115e38538f559d621be5688f3cbe225de88496fa745d025aa52e013fce81ddb740686f00e5b0ff375eb2b9e4e0996284abda31a22bb97a9fa52357921d92de2dfd6eb4a086da09b326899215c3f902afc0d0c003016110b9fbeaa343ac04bce0359fd767027c9ff842215512090a621412487ba4a0a70112c60cae9ce8d94141ac59ce91f62f2952a7847f77cc5c6d84f3cd0697153748c01d12b314cb8f7c59ea9b4a9c509b514ab2bf74ee6c5b631a5ef0de4154d67d370195dff441d3ebd18d0da0ce73f22226aa50033f445cec5c0850d6fc084fb30710dde958a0971d61fd98d23bc51059484152bfe4c5119b5545b24c9df1329675cc4671d64b81777e4d32b203c4a17d13a62bd2597731ad663a93e82af8d4e6168ede094021e8453d27f8991e2639bf20909b0dd5f3fac7d217876e5122d6445d2a550fcc84bdff76cb7f0cb53841050d33b9e4baa5ded8eba9415571502ebec614d5a6903b4b6d4cfbf02339a74c936983c050cc88c967c001c892cc00c751c53f5dec28a0922a3ed8986d231113d4ee35e600d368cd3354ea37c4510d6473148c98bf1752ac584db8d7d7d8f21e0da63593c58d84587c44b3df4bde501a9e3297c7997a8bb764e12e818842829a4565c06b1bf819b3083abf2485a3efeedef48a34805676bea5712105bf17f7ea5d52e741eea74f9317dedf7f274a926fade546bd7458aaba236826967f2c7b9f1d8d5cb6099b1d6cdab416a1e0c097dc5ed572ba71664af43e3654b0172eaf349fa02938caad7d3c187c315245d658c8d0630789884f95f6b6585f94889d23f5fc6f0307df6a15986e30f9f732728dce9f435390724937f730df7e3f807de840bfa24e3bcefa1de6cd403fc7fdaf68f8a8e02fa851752284cb4bf4bc6baad2681cb776544f6d766fee6ee6c9ad78725450e3402a902164300f1ea2fded66aa5407e0d842522d880def7e081b6fa4003f704405c76984f8c02f01dfc1f6f37a7910c6832c04abdbc5f2d0cb87a9b07847225df39aa112eeb7ec803c2b230a68cade4b95b9f4dc831da0252268b5eb1b10b482dc3ad71d52311df98d63bbe39b264bd2e7ac6ad48830c952d375afe910f4f35102f66b7ae12479b3dd9f5d5a49a64ae6518602254ef3c2eca8f7e65e22992621914efe565386cdd06f47a892a0c35089d660bf8ab6ff2c3836876d9c95cb8e46ba6b1983e8e7655c1227f3abc4a5013cea1ed680eae4dd1bbdebd810d9f0475320026baf544de012c6e0a0659018dac182e550342ea5751ea66c9ae86a10f855b976c7dd9f844264352fe89cd46dcb9c62d7d966176411259334e2c39212b711b04beed12245b068c74ecf539bce99e18de067e4331a6d6ffa3ffdc0023d39f68edf9eda2e122a0b177d598acd0f2f43c87c1a3e28676bc4c6816355def546377d599acd052bef606b068df5b870ea407f22d4a21b2550832820641bb0f4e4fb2f7113ab58292bfae2b7679016df0372c5af9f57689c6070469e0e460337ad260cc2b7307ec5adb27d3df6e9bffaf2537cb287feefcb4d087085030b956c282c483d6ef581649a46bdfd9b439abdbc839303c93743082d607a2e834f1fb5462f0c15fc44a5ed48356e8958b8689beaf6b86d7fe7e405fe78e8e7f408239769c51d3eae05ad1cbf7f378be4c075dedf53f4f552747ca3b1dedae442062ec9adc65bc13bd18ca81cc84ca0380bca7e4e564a8eca1dfa83a6ba630624f78151af976ebb569331f53ecb39c89bcc6319284cca83589df8a9904a0b018769af6865b8d5acae568632bb6e98aa98229d9a47298a52831ec34a6207b9cfbf95e6223b6c87f1c85dd4c96c8282ea7257463221066e5d2966b05811afd709621f532cced6f008957361bf5bae59df642b2656c9d44043b07e8f6a463e47368bd308d76211aa96cd6b6613d2b1784ad74b8f4a54f12ac2294c135537a8b9c5948c522fb1f6d18c378842aaed492b5fc7269d31f12497b5282390eb2652c09673d4c063b9d42b65ca8a30c37d3e90fbc775a3cd95c14b4b48c752dc90a14beae9a5ab7f4a6153833494f8dc13538282937a08cf9a738fac314a5e728efb931244cc70d259d6024d4c75539b2229e666539ba7d454ecdd0acab01b39cc5cb0e16c02027c51b277631106da55ee0ba88ae453c382dfab8a02f22f506b56481b692eebdb03b0529b1c9d4998af6c8bda50f481bb6d80ec728a7eaff7faa1acff4017a023cf6026219d6768554dbf345ca03d138351ac6305f0999fe70155aa4084ba0e43af13f96f49c13d087e933b65b343ae8fac05e45445e480091c5c985767a0ee95f0c5cee460bc2e2c27432a7c98f672dc86496270ada5601f4f995a5579cefd2ba8ce941538ad8a6412b5a6f3d778735c97ad2201633ea4fb8d5f07535c37d2b56232367480f0e6035b74db8f03f8f005bd21ada4ebdf9684deb8f4f865adc7656626e5ff223595dcae196409175e0231eae1bf56651aa9d4bb89eec246786928e685749c97081c39b2568fe0fff5abe0957de3f3d0ac272da16f25fdb407f058dbe66da822fcc0a3a63cec00bdb2fd031dd4744a1a7f658ee300632bbdf90f8225e84ebb89806a85e8a521d472465d2de82978514193ec5dd7cdcd05a88d48e9c145caab6192c22eacd287e1a82329116fe2706d55edae31a538ab0eefb87465fe4bcc606ff440c3fe8db4413bc1541ab7894e163848f4431f2d4aaf8fcac145399491a39f7501616194277fe8f0bdf009f5e1a691e211f762b1b4f629fe3328e000c6393462d21644d91478fb58954928f98a341469cceb79a1f3b880cc3b7e05d6f5f5d4d3fc16447af01f83b01d2d9b24d662905d9e56ac6f6fc87a46149390b712ad6d53d9024fc424490b0d619f1a4d2823c5184f4a49bd27d8db854c401f49eddfaba8f70652949c636ff88b8d7fbbfc53f8e2a834b8bc4fcafa55d2a3c8b9d93b212f091d361e6de6ae3188f910f5ef0591a55c1ef6c81e461416354167147b242b40a45ee565496576be743447cbcb392c0d243038088c7e3d081ecb633103d277403898085e59ad05aad359ebc3f392edb20494afbac0c2d390d6845f869c201a9df798c2df119d0c5379040f7dcbb6e55e67e19c24fda46f03a3177254f756a82bf826b851ae78cd75c547d5cac404ed4859c9984003f9233f12cc40882f6e605235404de74e0ac445e130602044d2d94fabb074b827f431208e567f13994f2c9d1d1c190a0df5e9891762a9b502cc70dc7e5e53032adf4f272a86402c99908a31053c1e031b6c6676ddc17a95ec86ffb0e6b875fd02a2891709d63aac32968fb8d6ef42f143b647070686a105d23980ef685eb9aeaee939a2fefe719235dd6b29e2a6fc60e064ae90d69ef10c2a969e75c322ca8f7e9777b934d9b995f41a8b8482b8a1cc1dc0e48c741ccfd6b10ce9c8acd0d0b6dc63b9ad44c7aa7871a16a91f5b5309af043d4b45cc8091a7882147c12ed345f16721b73a03437e088774d3b2794a31d4e807fd74bc42f9689f49ad79847fee30502855bc2c9dcb8b6f3f5bfcae591759323c297a478082a71c4e17ab3a19cc2e334ab450de908f36ff320e515f8780ca6bec4a72d9b1b46828f54c7a7f01c40a0bacbf8209efe6774b2a60ace40e13766766925142762ac6e39cc3a9f85c406528a16dd55c9c3ea0d21b36c10c9a306427b1aa647564701bd9ac82ae47c3ba8fe000a1f4c47efeb80d9539719df29cd30737233c15a4bbb415f1a3f16c8e7f3bb7726351680f73e84da4659ef0ec094b6650ae38069b7b9e28d3850e8c92cf176fe6274b81f1144dd85f0c5bd1ca869fb4528ff2ca4551ef2ea80a787c43c11521e4aa817c82dde954ba4aeb5ccd3c553c9d38593d847031abd820f4c2ed059144e1a5759a915d4c4bb192f95156514079c960910a6839be9583dc741e8e5f08a099862f2bd320e778ae6e5d3c319c7ee79dcb3e12897a822ed771b35e04013296dd76e86efc2fce4ed8671abfd7008b1b2841a3ed2ab0bdc08c49b9c7f32e868a46fe3f1fdda50b155f7dbc1ccd584404f640b50a5da02be33ed24ca5b8a75e88890c1abfb6b7792912d1eff40158bc130e65ff3484e16834984ac85193ce5ebc6229cfc81be0615c62e3fd2cb17f3dfc340440ac19a261f29a3c338c6a6b789889099e615275f672d028231ca4c836180a61a28ae6353996294c5bebd3b03038f48f3d001dcbe3b12b53e70283a76007aba90b4466490ac1e928a3e7a4c98f83310bccd1a80c0d6fdfab8ed64b67d121862f5a8d50bb0cc49b7309375bdfc3475a30328b2b5d41c19d1ad148744a2f1c53b989bef1f696bcce3ea48d68be49d0b45094336f2e65f30821ef1f3989ebbd09367a55f87b0ee2106a3e5a7244c11f6d7566186d85e686c843e3c259241c78b90c46fe81d28c0688be1dbf1d0815076e192baa76fe28fb7ef6437e339f8d26fcadd82b76d0bd7d241a5ebc5aefb92c042832731329ab22354384550f16d0b3daec3ed25ab7bb39772a5c040e3588945b6231c406708d5b956c79bb4e3e0bb516f685b56f1375cae1ef67d848d866f794844dfdc5ec800c631829a94fcceb23bf363f6adabcb2327119da7a0b00fc6e3d3df36bf1fa249144837c2406cc7d8b3e1e849da530d65949c6671d7e91d48f021e44d1120442bf04c92805fbc6c5a6d0a434d8e474a984c4dfa0cfd90cef1a7b9a0f8e363d49abb34b20233184b0b8a2fd7d9b07cd39b2d0277012363e45780af1374d9b2b3dc90bf5096c875da08aa357c444a19601397df2ef828fd4253983ee566e13928a5c60a60a56097ca2ab014290aca970713a6ce005853eaef4bd08beffc4262b76fb25015b96c108c221ef1acdb9b6da62a09a388b1bd55557cbed09063e3b758bac3db9a9091fb5b0ced6fc2428beb54d9a3599bb8b1b39dc17d923c2766b4d279ad97c53fb77cf0358072718fa3795dbec6670b74e741b1eb06053d59f1b5a4de1a54a68c61ed24f230ff4f8a3db7143b53c2e72feee8fa140f4978d5f6142794d742a4022104d63efaf0eb55f9f693f9193421aa07f49e492df47d8164170012c7b8ffc40f46e2670718acfd46f017dd3dfcc6ef466f05ad0c287fa3ac0b7ddc893a8a5418c65b3dc30f035f566c045799505af7474dcd6c131faa1aa0962a9d6d1dfcb82460236524b14586ebfa000d8032088354b0557e9497b904f723b3ff8b3197ee59dd865d3c4ced8957cc3fab7b3320e6daeccfbf72b3baafdda80bcb7255a6306f15f561a283a9dd1d504e0fd2718ca9c35a2510d07b2e2df44aa033fbba17624e306b5e3d9bf7fa2523d8ce31c1963893cd8ea01c446afd440688436b704027f03c215b55d849c492418aed911b4930592da7b0133fc2c66ca6a3b1032590ebf3009cfc089e074c76a62bf42e9c464b30f35a59d3e6e6b810cecfe3c9f58a3f6d5cc4662cdf803243bfb153367dbf39f556734fd12c9472b6d09a2c51502d6f8c244b2340a48f936096ed4c52b771094a62069a1d98052fbce50be3e97d3d2767936988f3f0bb78fbf242f7d7eb9feb09e4b89e2e174fd3c81d446279f4c5e23e9426d648888dae6519b27e95a80e0aa9517b83201166502018be0eefea51e173df21375a9fdb29276a5dc12f87430ee75785f108433fee00e183830295772876dd721c3e456bf83c5a160b823e8ff580e8b62a2fffe1f48aa85e02b815909c73c7daa6e6947a92a45c61029f261fe2d2853fbc306641211f3f4722e374aa9fd84d47a5ebd2e2291fded2efb5f42c01c37fa51129a6f817d9405c23f6fd5a971f8861953f8dc64077e9888a926e48d37da1d0ee114400eb9ec8d9f9a32761cc483d40d302279e2eb03dade2d0d84bfc9769bae09fba1518f5c9487da53453be3bb8370125e11ff52f3ec65e9e644eb355d03e55484f06c71c23aafeb53c435db9ac2d19c3fd8e5235e0064010838c5d86c75fd5d9061123cfb852b15c710c5a831854f595469f4660d43ca093ee5259561c32ed58c91b323dfddafacdba30af57aa417d3e6d5f48e97a7b91a677d014e3ee6378172263e1b6cdf67dee62463a183d40723ae8144a3adda3fa47f6c43ac03d43eb358bfc8cf46e947a29f25e5677bc3636692491f288877767c1c94c588cf705bb3ec0b4064e6a6305c92b212a362ccc46113d409ae331863af6c23dafd24ee1e98cd95e26a82b2541601abfab5438d97bba7dbf5f1fd5321058032a5a11ce95949a2f62badf7bc0ce92db7393079bc76bb3c1ce0914e465afdd826e01556f278ae21c4dab0227eb963d098e76f1bd8235c99211a71ed976eb0eb116e20eb3edd99968c107a3962ae4837c7e6c035d92dc7dc35bbdff881c9ac032b01e5f9dd4566d18145cdeea239a600d40b87bd9e47a5a5c5cdb03762cb193984642c3bd7f96cb4115e35b4bcec77d6556d9580cdb87e811f613dd2e49682ef0aa2173e64cccaee2b7de3aa20c25d11633d02b9448cc8cec0febf2d440189ef324e0ec90d2b9b01c010ed81c6f86cc0835f5a39f6e266fd4d5785c8021ff4439228c244c7fd7e31e8c7c5fb68e67ff08d6e43ac4a39debce82d94e7390cc7b176823a6e945fd01f507b9cd66e54f7fe3202ce849ad82737f0dc2e54ba22d6f38e7c283a2911be610604ff5456b63183cd92cbaa20c495d6e73b86ba75f8ec8fdb006d12da05945ea9014c31b1fe4b52a06363061dc8bffe1a95311fbae4a6ed16e333e528e95afbd23de78f945bc41c6032e78ed1a3e4582ce64b2613ec22f8146fa706f5f140e40064174cdd040f71c20351d719fc07b6e8080840ab773d4573f07aa7f9ac2ded033f9ae22ba18d4aaf98d85b5e381cc7177c99c27a306f6511d0def1fc262cb27bd6a24c9051f01520b088c449057a48b1916d9398a4cc4d9f0e02b99f10c50c03d6b8121b11482834c4158c2d325575516e6162070ca3fc7c6bf67f855808d9131edfb28b2ed1d102cb441c63c9d36a70960a9770ac8fd5d9f64df406bcd07b709881e1429bf334ee58c0500dcc45527a9ff59fac44a4bfb152192ef732d562a56bb49c8a79c4324ae3636e58d7e1781a5d500e8bc190f0815eb18c1d40326750d3ac9404afea2c35243d0ee2c8a24a13144696f0dc4e293f0690aa81baaa65c84938791bd0664dd051a84149f23aaaa620373f5f3f60860d354b05c41fccb8c05c421c0e3256c82386017a3860b762a0df327a46431fab1b30fc02", - "0x3a65787472696e7369635f696e646578": "0x00000000", - "0x3a6772616e6470615f617574686f726974696573": "0x01200e6d7d1afbcc6547b92995a394ba0daed07a2420be08220a5a1336c6731f0bfa0100000000000000fcd5f87a6fd5707a25122a01b4dac0a8482259df7d42a9a096606df1320df08d0100000000000000e1b68fbd84333e31486c08e6153d9a1415b2e7e71b413702b7d64e9b631184a1010000000000000036be9069cdb4a8a07ecd51f257875150f0a8a1be44a10d9d98dabf10a030aef401000000000000006c878e33b83c20324238d22240f735457b6fba544b383e70bb62a27b57380c810100000000000000d9c056c98ca0e6b4eb7f5c58c007c1db7be0fe1f3776108f797dd4990d1ccc3301000000000000004bea0b37e0cce9bddd80835fa2bfd5606f5dcfb8388bbb10b10c483f0856cf1401000000000000004ee66173993dd0db5d628c4c9cb61a27b76611ad3c3925947f0d0011ee2c5dcc0100000000000000", - "0x3d9cad2baf702e20b136f4c8900cd8024e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x3f1467a096bcd71a5b6a0c8155e20810308ce9615de0775a82f8a94dc3d285a1": "0x01", - "0x3f1467a096bcd71a5b6a0c8155e208104e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x3fba98689ebed1138735e0e7a5a790ab4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x3fba98689ebed1138735e0e7a5a790abee99a84ccbfb4b82e714617e5e06f6f7": "0xd0070000", - "0x42b50b77ef717947e7043bb52127d6654e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x4da2c41eaffa8e1a791c5d65beeefd1f028685274e698e781f7f2766cba0cc8300000000": "0x200500000003000000040000000200000001000000060000000000000007000000abc3f086f5ac20eaab792c75933b2e196307835a61a955be82aa63bc0ff9617a06000000201efc23c0b51ad609ab670ecf45807e31acbd8e7e5cb7c07cf49ee42992d2867c882d72965e642677583b333b2d173ac94b5fd6c405c76184bb14293be748a13b6a8570b9c6408e54bacf123cc2bb1b0f087f9c149147d0005badba63a5a4ac01a8e61ffacafaf546283dc92d14d7cc70ea0151a5dd81fdf73ff5a2951f2b6037669a10892119453e9feb4e3f1ee8e028916cc3240022920ad643846fbdbee816042f07fc5268f13c026bbe199d63e6ac77a0c2a780f71cda05cee5a6f1b3f11f0e07a51d3213842f8e9363ce8e444255990a225f87e80a3d651db7841e1a0205d822d4088b20dca29a580a577a97d6f024bb24c9550bebdfd7d2d18e946a1c7d000000000000000000000000000000000000000100000000000000", - "0x4da2c41eaffa8e1a791c5d65beeefd1f4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", - "0x4da2c41eaffa8e1a791c5d65beeefd1fff4a51b74593c3708682038efe5323b5": "0x00000000", - "0x50e709b04947c0cd2f04727ef76e88f64e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x5c0d1176a568c1f92944340dbfed9e9c4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x5c0d1176a568c1f92944340dbfed9e9c530ebca703c85910e7164cb7d1c9e47b": "0x52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649", - "0x5f9cc45b7a00c5899361e1c6099678dc4e7b9012096b41c4eb3aaf947f6ea429": "0x0400", - "0x5f9cc45b7a00c5899361e1c6099678dc8a2d09463effcc78a22d75b9cb87dffc": "0x0000000000000000", - "0x5f9cc45b7a00c5899361e1c6099678dcd47cb8f5328af743ddfb361e7180e7fcbb1bdbcacd6ac9340000000000000000": "0x00000000", - "0x63f78c98723ddc9073523ef3beefda0c4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x6a0da05ca59913bc38a8630590f2627c2a351b6a99a5b21324516e668bb86a57": "0x00", - "0x6a0da05ca59913bc38a8630590f2627c4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x6ac983d82528bf1595ab26438ae5b2cf4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x6cf4040bbce30824850f1a4823d8c65f4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x70f943199f1a2dde80afdaf3f447db834e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x7474449cca95dc5d0c00e71735a6d17d4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x94eadf0156a8ad5156507773d0471e4a16973e1142f5bd30d9464076794007db": "0x00", - "0x94eadf0156a8ad5156507773d0471e4a1e8de4295679f32032acb318db364135": "0x00", - "0x94eadf0156a8ad5156507773d0471e4a4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x94eadf0156a8ad5156507773d0471e4a64fb6e378f53d72f7859ad0e6b6d8810": "0x0000000000", - "0x94eadf0156a8ad5156507773d0471e4a9ce0310edffce7a01a96c2039f92dd10": "0x01000000", - "0x94eadf0156a8ad5156507773d0471e4ab8ebad86f546c7e0b135a4212aace339": "0x00", - "0x9ba1b78972885c5d3fc221d6771e8ba24e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0x9ba1b78972885c5d3fc221d6771e8ba29611a984bbd04e2fd39f97bbc006115f": "0x01", - "0x9ba1b78972885c5d3fc221d6771e8ba2fe6d4a58cccf03d052c50ccbfa0311c7": "0x52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649", - "0xa8c65209d47ee80f56b0011e8fd91f504e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xb341e3a63e58a188839b242d17f8c9f82586833f834350b4d435d5fd269ecc8b": "0x200500000003000000040000000200000001000000060000000000000007000000", - "0xb341e3a63e58a188839b242d17f8c9f84e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e": "0x201efc23c0b51ad609ab670ecf45807e31acbd8e7e5cb7c07cf49ee42992d2867c882d72965e642677583b333b2d173ac94b5fd6c405c76184bb14293be748a13b6a8570b9c6408e54bacf123cc2bb1b0f087f9c149147d0005badba63a5a4ac01a8e61ffacafaf546283dc92d14d7cc70ea0151a5dd81fdf73ff5a2951f2b6037669a10892119453e9feb4e3f1ee8e028916cc3240022920ad643846fbdbee816042f07fc5268f13c026bbe199d63e6ac77a0c2a780f71cda05cee5a6f1b3f11f0e07a51d3213842f8e9363ce8e444255990a225f87e80a3d651db7841e1a0205d822d4088b20dca29a580a577a97d6f024bb24c9550bebdfd7d2d18e946a1c7d", - "0xb341e3a63e58a188839b242d17f8c9f8b5cab3380174032968897a4c3ce57c0a": "0x00000000", - "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1": "0x01", - "0xc2261276cc9d1f8598ea4b6a74b15c2f4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xc2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80": "0x0000362b4c8ee30d0000000000000000", - "0xca32a41f4b3ed515863dc0a38697f84e4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xcd710b30bd2eab0352ddcc26417aa1944e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xcd710b30bd2eab0352ddcc26417aa1949f4993f016e2d2f8e5f43be7bb259486": "0x00", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb319b9aeb2f5add22992ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f": "0xe1b68fbd84333e31486c08e6153d9a1415b2e7e71b413702b7d64e9b631184a1d2644c1ab2c63a3ad8d40ad70d4b260969e3abfe6d7e6665f50dc9f6365c9d2aee93e26259decb89afcf17ef2aa0fa2db2e1042fb8f56ecfb24d19eae8629878a8e61ffacafaf546283dc92d14d7cc70ea0151a5dd81fdf73ff5a2951f2b6037244f3421b310c68646e99cdbf4963e02067601f57756b072a4b19431448c186e2c57f81fd311c1ab53813c6817fe67f8947f8d39258252663b3384ab4195494d039d065fe4f9234f0a4f13cc3ae585f2691e9c25afa469618abb6645111f607a53", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3328718e032416872520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a": "0xfcd5f87a6fd5707a25122a01b4dac0a8482259df7d42a9a096606df1320df08d38757d0de00a0c739e7d7984ef4bc01161bd61e198b7c01b618425c16bb5bd5f48a910c0af90898f11bd57d37ceaea53c78994f8e1833a7ade483c9a84bde055669a10892119453e9feb4e3f1ee8e028916cc3240022920ad643846fbdbee81668bf52c482630a8d1511f2edd14f34127a7d7082219cccf7fd4c6ecdb535f80df6f8fe475130d21165446a02fb1dbce3a7bf36412e5d98f4f0473aed9252f34903a90c2bb6d3b7000020f6152fe2e5002fa970fd1f42aafb6c8edda8dacc2ea77e", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb33bb8d7990ae3975438f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404": "0x36be9069cdb4a8a07ecd51f257875150f0a8a1be44a10d9d98dabf10a030aef4764186bc30fd5a02477f19948dc723d6d57ab174debd4f80ed6038ec960bfe218e95b9b5b4dc69790b67b566567ca8bf8cdef3a3a8bb65393c0d1d1c87cd2d2c882d72965e642677583b333b2d173ac94b5fd6c405c76184bb14293be748a13b821271c99c958b9220f1771d9f5e29af969edfa865631dba31e1ab7bc0582b752496f28d887d84705c6dae98aee8bf90fc5ad10bb5545eca1de6b68425b70f7c0307d29bbf6a5c4061c2157b44fda33b7bb4ec52a5a0305668c74688cedf288d58", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb393c0875f4080dabc8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47": "0x4ee66173993dd0db5d628c4c9cb61a27b76611ad3c3925947f0d0011ee2c5dccda6b2df18f0f9001a6dcf1d301b92534fe9b1f3ccfa10c49449fee93adaa834992156f54a114ee191415898f2da013d9db6a5362d6b36330d5fc23e27360ab66d822d4088b20dca29a580a577a97d6f024bb24c9550bebdfd7d2d18e946a1c7d481538f8c2c011a76d7d57db11c2789a5e83b0f9680dc6d26211d2f9c021ae4c4e262811acdfe94528bfc3c65036080426a0e1301b9ada8d687a70ffcae99c26025e84e95ed043e387ddb8668176b42f8e2773ddd84f7f58a6d9bf436a4b527986", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3c25dd840975e8979fa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00": "0x4bea0b37e0cce9bddd80835fa2bfd5606f5dcfb8388bbb10b10c483f0856cf14720537e2c1c554654d73b3889c3ef4c3c2f95a65dd3f7c185ebe4afebed78372560d90ca51e9c9481b8a9810060e04d0708d246714960439f804e5c6f40ca651042f07fc5268f13c026bbe199d63e6ac77a0c2a780f71cda05cee5a6f1b3f11ffab485e87ed1537d089df521edf983a777c57065a702d7ed2b6a2926f31da74f64d59feddb3d00316a55906953fb3db8985797472bd2e6c7ea1ab730cc339d7f033f1a6d47fe86f88934e4b83b9fae903b92b5dcf4fec97d5e3e8bf4f39df03685", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3d560e0b6940e074462475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a": "0x0e6d7d1afbcc6547b92995a394ba0daed07a2420be08220a5a1336c6731f0bfaa076ef1280d768051f21d060623da3ab5b56944d681d303ed2d4bf658c5bed3586975a37211f8704e947a365b720f7a3e2757988eaa7d0f197e83dba355ef7430e07a51d3213842f8e9363ce8e444255990a225f87e80a3d651db7841e1a0205ec60e71fe4a567ef9fef99d4bbf37ffae70564b41aa6f94ef0317c13e0a5477bf49eae66a0ac9f610316906ec8f1a0928e20d7059d76a5ca53cbcb5a9b50dd3c034f68c5661a41930c82f26a662276bf89f33467e1c850f2fb8ef687fe43d62276", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3dc18ebe8d771cfa002ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864": "0xd9c056c98ca0e6b4eb7f5c58c007c1db7be0fe1f3776108f797dd4990d1ccc33bab3cccdcc34401e9b3971b96a662686cf755aa869a5c4b762199ce531b12c5bc4a980da30939d5bb9e4a734d12bf81259ae286aa21fa4b65405347fa40eff351efc23c0b51ad609ab670ecf45807e31acbd8e7e5cb7c07cf49ee42992d2867c4c64d3f06d28adeb36a892fdaccecace150bec891f04694448a60b74fa469c22160ea09c5717270e958a3da42673fa011613a9539b2e4ebcad8626bc117ca04a020019a8bb188f8145d02fa855e9c36e9914457d37c500e03634b5223aa5702474", - "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3df32aff68041374f02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16": "0x6c878e33b83c20324238d22240f735457b6fba544b383e70bb62a27b57380c817c94715e5dd8ab54221b1b6b2bfa5666f593f28a92a18e28052531de1bd80813d2f9d537ffa59919a4028afdb627c14c14c97a1547e13e8e82203d2049b15b1a6a8570b9c6408e54bacf123cc2bb1b0f087f9c149147d0005badba63a5a4ac0116c69ea8d595e80b6736f44be1eaeeef2ac9c04a803cc4fd944364cb0d617a33306ac5c772fe858942f92b6e28bd82fb7dd8cdd25f9a4626c1b0eee075fcb53102fb0330356e63a35dd930bc74525edf28b3bf5eb44aab9e9e4962c8309aaba6a6", - "0xcec5070d609dd3497f72bde07fc96ba04e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950091b1bd4e8d4c12061756469802496f28d887d84705c6dae98aee8bf90fc5ad10bb5545eca1de6b68425b70f7c": "0x38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195009ab51029a10e53570617261800e07a51d3213842f8e9363ce8e444255990a225f87e80a3d651db7841e1a0205": "0x62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19500a3d203cf823b13d6173676e80821271c99c958b9220f1771d9f5e29af969edfa865631dba31e1ab7bc0582b75": "0x38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19500d1064d79ff558056772616e800e6d7d1afbcc6547b92995a394ba0daed07a2420be08220a5a1336c6731f0bfa": "0x62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195012b62e212b6a7a9c696d6f6e808e95b9b5b4dc69790b67b566567ca8bf8cdef3a3a8bb65393c0d1d1c87cd2d2c": "0x38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195012fefbc5e5cee2846173676e80fab485e87ed1537d089df521edf983a777c57065a702d7ed2b6a2926f31da74f": "0xfa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950149cf457032f53e57061726180d822d4088b20dca29a580a577a97d6f024bb24c9550bebdfd7d2d18e946a1c7d": "0x8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19501b1525326b5d47776772616e80fcd5f87a6fd5707a25122a01b4dac0a8482259df7d42a9a096606df1320df08d": "0x520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19501e69501baac264d4696d6f6e80ee93e26259decb89afcf17ef2aa0fa2db2e1042fb8f56ecfb24d19eae8629878": "0x92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195021e85cbadb3ce9a26772616e806c878e33b83c20324238d22240f735457b6fba544b383e70bb62a27b57380c81": "0x02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19502d2937d2d9650f057061726180a8e61ffacafaf546283dc92d14d7cc70ea0151a5dd81fdf73ff5a2951f2b6037": "0x92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19502e5e3ed1cdc323ab626565668402fb0330356e63a35dd930bc74525edf28b3bf5eb44aab9e9e4962c8309aaba6a6": "0x02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19503639d22ceafce3266265656684020019a8bb188f8145d02fa855e9c36e9914457d37c500e03634b5223aa5702474": "0x02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19503c0791148c7780b8626162658038757d0de00a0c739e7d7984ef4bc01161bd61e198b7c01b618425c16bb5bd5f": "0x520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19503c75eb9438a505fc6261626580a076ef1280d768051f21d060623da3ab5b56944d681d303ed2d4bf658c5bed35": "0x62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19503d7dc9205a149f6a6175646980306ac5c772fe858942f92b6e28bd82fb7dd8cdd25f9a4626c1b0eee075fcb531": "0x02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19503eaa3e59477bc9506261626580720537e2c1c554654d73b3889c3ef4c3c2f95a65dd3f7c185ebe4afebed78372": "0xfa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950417ebe2c60c84ed5626565668403a90c2bb6d3b7000020f6152fe2e5002fa970fd1f42aafb6c8edda8dacc2ea77e": "0x520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950438ac98f6d864839696d6f6e80d2f9d537ffa59919a4028afdb627c14c14c97a1547e13e8e82203d2049b15b1a": "0x02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195043d506aedab0d2ce696d6f6e8048a910c0af90898f11bd57d37ceaea53c78994f8e1833a7ade483c9a84bde055": "0x520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195043f25e7a03a30387696d6f6e8092156f54a114ee191415898f2da013d9db6a5362d6b36330d5fc23e27360ab66": "0x8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195054435a901133fb946173676e8016c69ea8d595e80b6736f44be1eaeeef2ac9c04a803cc4fd944364cb0d617a33": "0x02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950585cf1f6f8e46326696d6f6e8086975a37211f8704e947a365b720f7a3e2757988eaa7d0f197e83dba355ef743": "0x62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950636f684eb09a15046772616e80d9c056c98ca0e6b4eb7f5c58c007c1db7be0fe1f3776108f797dd4990d1ccc33": "0x02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195068dec3fce5ade0966261626580da6b2df18f0f9001a6dcf1d301b92534fe9b1f3ccfa10c49449fee93adaa8349": "0x8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195075a33a2ed5ac2cdc6265656684034f68c5661a41930c82f26a662276bf89f33467e1c850f2fb8ef687fe43d62276": "0x62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950776743a4ae520892617564698064d59feddb3d00316a55906953fb3db8985797472bd2e6c7ea1ab730cc339d7f": "0xfa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19507acca078b878d43a70617261801efc23c0b51ad609ab670ecf45807e31acbd8e7e5cb7c07cf49ee42992d2867c": "0x02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19507d9c46786caf74af6261626580d2644c1ab2c63a3ad8d40ad70d4b260969e3abfe6d7e6665f50dc9f6365c9d2a": "0x92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19507f532159f03d44eb6175646980f49eae66a0ac9f610316906ec8f1a0928e20d7059d76a5ca53cbcb5a9b50dd3c": "0x62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19508248d97b4996007070617261806a8570b9c6408e54bacf123cc2bb1b0f087f9c149147d0005badba63a5a4ac01": "0x02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195097e3e605d1b3579b6173676e804c64d3f06d28adeb36a892fdaccecace150bec891f04694448a60b74fa469c22": "0x02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509df5f4072c4244956261626580764186bc30fd5a02477f19948dc723d6d57ab174debd4f80ed6038ec960bfe21": "0x38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950a00d3cb0425699a66772616e804bea0b37e0cce9bddd80835fa2bfd5606f5dcfb8388bbb10b10c483f0856cf14": "0xfa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950a068f246c1094c1462656566840307d29bbf6a5c4061c2157b44fda33b7bb4ec52a5a0305668c74688cedf288d58": "0x38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950a31727416d0095b96772616e80e1b68fbd84333e31486c08e6153d9a1415b2e7e71b413702b7d64e9b631184a1": "0x92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950a9e62b8a5c8760f06265656684033f1a6d47fe86f88934e4b83b9fae903b92b5dcf4fec97d5e3e8bf4f39df03685": "0xfa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950ab7b30d24546522861756469804e262811acdfe94528bfc3c65036080426a0e1301b9ada8d687a70ffcae99c26": "0x8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950bad35ce880ec90d4696d6f6e80c4a980da30939d5bb9e4a734d12bf81259ae286aa21fa4b65405347fa40eff35": "0x02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d1e1b030b162ca447061726180042f07fc5268f13c026bbe199d63e6ac77a0c2a780f71cda05cee5a6f1b3f11f": "0xfa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d31ed6cbd51d9f636265656684039d065fe4f9234f0a4f13cc3ae585f2691e9c25afa469618abb6645111f607a53": "0x92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d46d2cb2a4d496b46265656684025e84e95ed043e387ddb8668176b42f8e2773ddd84f7f58a6d9bf436a4b527986": "0x8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d7ce35a3ce71c3d76175646980160ea09c5717270e958a3da42673fa011613a9539b2e4ebcad8626bc117ca04a": "0x02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950deeb3985cefbdfa47061726180882d72965e642677583b333b2d173ac94b5fd6c405c76184bb14293be748a13b": "0x38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950e193783dd6b845ea6173676e80ec60e71fe4a567ef9fef99d4bbf37ffae70564b41aa6f94ef0317c13e0a5477b": "0x62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950e592f5ef74f560666173676e8068bf52c482630a8d1511f2edd14f34127a7d7082219cccf7fd4c6ecdb535f80d": "0x520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950e7240ce913e160eb6261626580bab3cccdcc34401e9b3971b96a662686cf755aa869a5c4b762199ce531b12c5b": "0x02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950e887ec3d30b64e896173676e80481538f8c2c011a76d7d57db11c2789a5e83b0f9680dc6d26211d2f9c021ae4c": "0x8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950ed0b865484219eb06173676e80244f3421b310c68646e99cdbf4963e02067601f57756b072a4b19431448c186e": "0x92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950ee41af0530f856db6772616e8036be9069cdb4a8a07ecd51f257875150f0a8a1be44a10d9d98dabf10a030aef4": "0x38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950ef9482dba3e5b0d862616265807c94715e5dd8ab54221b1b6b2bfa5666f593f28a92a18e28052531de1bd80813": "0x02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950f5bc812467e867ac7061726180669a10892119453e9feb4e3f1ee8e028916cc3240022920ad643846fbdbee816": "0x520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950f6584bfaf470c1b26175646980f6f8fe475130d21165446a02fb1dbce3a7bf36412e5d98f4f0473aed9252f349": "0x520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950f7aec8a47707294b61756469802c57f81fd311c1ab53813c6817fe67f8947f8d39258252663b3384ab4195494d": "0x92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950f8df002813b43b80696d6f6e80560d90ca51e9c9481b8a9810060e04d0708d246714960439f804e5c6f40ca651": "0xfa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00", - "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950feca8028a77ba7626772616e804ee66173993dd0db5d628c4c9cb61a27b76611ad3c3925947f0d0011ee2c5dcc": "0x8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47", - "0xcec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903": "0x2062475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a040402a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b1602ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864fa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a008062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47", - "0xcec5070d609dd3497f72bde07fc96ba0e0cdd062e6eaf24295ad4ccfc41d4609": "0x2062475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a0e6d7d1afbcc6547b92995a394ba0daed07a2420be08220a5a1336c6731f0bfaa076ef1280d768051f21d060623da3ab5b56944d681d303ed2d4bf658c5bed3586975a37211f8704e947a365b720f7a3e2757988eaa7d0f197e83dba355ef7430e07a51d3213842f8e9363ce8e444255990a225f87e80a3d651db7841e1a0205ec60e71fe4a567ef9fef99d4bbf37ffae70564b41aa6f94ef0317c13e0a5477bf49eae66a0ac9f610316906ec8f1a0928e20d7059d76a5ca53cbcb5a9b50dd3c034f68c5661a41930c82f26a662276bf89f33467e1c850f2fb8ef687fe43d62276520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022afcd5f87a6fd5707a25122a01b4dac0a8482259df7d42a9a096606df1320df08d38757d0de00a0c739e7d7984ef4bc01161bd61e198b7c01b618425c16bb5bd5f48a910c0af90898f11bd57d37ceaea53c78994f8e1833a7ade483c9a84bde055669a10892119453e9feb4e3f1ee8e028916cc3240022920ad643846fbdbee81668bf52c482630a8d1511f2edd14f34127a7d7082219cccf7fd4c6ecdb535f80df6f8fe475130d21165446a02fb1dbce3a7bf36412e5d98f4f0473aed9252f34903a90c2bb6d3b7000020f6152fe2e5002fa970fd1f42aafb6c8edda8dacc2ea77e92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6fe1b68fbd84333e31486c08e6153d9a1415b2e7e71b413702b7d64e9b631184a1d2644c1ab2c63a3ad8d40ad70d4b260969e3abfe6d7e6665f50dc9f6365c9d2aee93e26259decb89afcf17ef2aa0fa2db2e1042fb8f56ecfb24d19eae8629878a8e61ffacafaf546283dc92d14d7cc70ea0151a5dd81fdf73ff5a2951f2b6037244f3421b310c68646e99cdbf4963e02067601f57756b072a4b19431448c186e2c57f81fd311c1ab53813c6817fe67f8947f8d39258252663b3384ab4195494d039d065fe4f9234f0a4f13cc3ae585f2691e9c25afa469618abb6645111f607a5338f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a040436be9069cdb4a8a07ecd51f257875150f0a8a1be44a10d9d98dabf10a030aef4764186bc30fd5a02477f19948dc723d6d57ab174debd4f80ed6038ec960bfe218e95b9b5b4dc69790b67b566567ca8bf8cdef3a3a8bb65393c0d1d1c87cd2d2c882d72965e642677583b333b2d173ac94b5fd6c405c76184bb14293be748a13b821271c99c958b9220f1771d9f5e29af969edfa865631dba31e1ab7bc0582b752496f28d887d84705c6dae98aee8bf90fc5ad10bb5545eca1de6b68425b70f7c0307d29bbf6a5c4061c2157b44fda33b7bb4ec52a5a0305668c74688cedf288d5802a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b166c878e33b83c20324238d22240f735457b6fba544b383e70bb62a27b57380c817c94715e5dd8ab54221b1b6b2bfa5666f593f28a92a18e28052531de1bd80813d2f9d537ffa59919a4028afdb627c14c14c97a1547e13e8e82203d2049b15b1a6a8570b9c6408e54bacf123cc2bb1b0f087f9c149147d0005badba63a5a4ac0116c69ea8d595e80b6736f44be1eaeeef2ac9c04a803cc4fd944364cb0d617a33306ac5c772fe858942f92b6e28bd82fb7dd8cdd25f9a4626c1b0eee075fcb53102fb0330356e63a35dd930bc74525edf28b3bf5eb44aab9e9e4962c8309aaba6a602ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864d9c056c98ca0e6b4eb7f5c58c007c1db7be0fe1f3776108f797dd4990d1ccc33bab3cccdcc34401e9b3971b96a662686cf755aa869a5c4b762199ce531b12c5bc4a980da30939d5bb9e4a734d12bf81259ae286aa21fa4b65405347fa40eff351efc23c0b51ad609ab670ecf45807e31acbd8e7e5cb7c07cf49ee42992d2867c4c64d3f06d28adeb36a892fdaccecace150bec891f04694448a60b74fa469c22160ea09c5717270e958a3da42673fa011613a9539b2e4ebcad8626bc117ca04a020019a8bb188f8145d02fa855e9c36e9914457d37c500e03634b5223aa5702474fa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a004bea0b37e0cce9bddd80835fa2bfd5606f5dcfb8388bbb10b10c483f0856cf14720537e2c1c554654d73b3889c3ef4c3c2f95a65dd3f7c185ebe4afebed78372560d90ca51e9c9481b8a9810060e04d0708d246714960439f804e5c6f40ca651042f07fc5268f13c026bbe199d63e6ac77a0c2a780f71cda05cee5a6f1b3f11ffab485e87ed1537d089df521edf983a777c57065a702d7ed2b6a2926f31da74f64d59feddb3d00316a55906953fb3db8985797472bd2e6c7ea1ab730cc339d7f033f1a6d47fe86f88934e4b83b9fae903b92b5dcf4fec97d5e3e8bf4f39df036858062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab474ee66173993dd0db5d628c4c9cb61a27b76611ad3c3925947f0d0011ee2c5dccda6b2df18f0f9001a6dcf1d301b92534fe9b1f3ccfa10c49449fee93adaa834992156f54a114ee191415898f2da013d9db6a5362d6b36330d5fc23e27360ab66d822d4088b20dca29a580a577a97d6f024bb24c9550bebdfd7d2d18e946a1c7d481538f8c2c011a76d7d57db11c2789a5e83b0f9680dc6d26211d2f9c021ae4c4e262811acdfe94528bfc3c65036080426a0e1301b9ada8d687a70ffcae99c26025e84e95ed043e387ddb8668176b42f8e2773ddd84f7f58a6d9bf436a4b527986", - "0xd57bce545fb382c34570e5dfbf338f5e4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xd5c41b52a371aa36c9254ce34324f2a54e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xd5e1a2fa16732ce6906189438c0a82c64e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xd8bbe27baf3aa64bb483afabc240f68e4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xd979a2ce97f43b91540066af95e5c2cd4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xda7d4185f8093e80caceb64da45219e34e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xe81713b6b40972bbcd298d67597a495f4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xe81713b6b40972bbcd298d67597a495f9611a984bbd04e2fd39f97bbc006115f": "0x01", - "0xe81713b6b40972bbcd298d67597a495ffe6d4a58cccf03d052c50ccbfa0311c7": "0x52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649", - "0xf0c365c3cf59d671eb72da0e7a4113c44e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xf5207f03cfdce586301014700e2c25934e7b9012096b41c4eb3aaf947f6ea429": "0x0000", - "0xf9922c78cfa3c316d27a3eb48145ab1b4e7b9012096b41c4eb3aaf947f6ea429": "0x0400" - }, - "childrenDefault": {} - } - } -} \ No newline at end of file diff --git a/node/service/src/chain_spec.rs b/node/service/src/chain_spec.rs index e2c0a7bfdf94..8650499d064c 100644 --- a/node/service/src/chain_spec.rs +++ b/node/service/src/chain_spec.rs @@ -767,10 +767,10 @@ fn kusama_staging_testnet_config_genesis(wasm_binary: &[u8]) -> kusama::GenesisC configuration: kusama::ConfigurationConfig { config: default_parachains_host_configuration(), }, - gilt: Default::default(), paras: Default::default(), xcm_pallet: Default::default(), nomination_pools: Default::default(), + nis_counterpart_balances: Default::default(), } } @@ -1073,11 +1073,11 @@ fn rococo_staging_testnet_config_genesis(wasm_binary: &[u8]) -> rococo_runtime:: configuration: rococo_runtime::ConfigurationConfig { config: default_parachains_host_configuration(), }, - gilt: Default::default(), registrar: rococo_runtime::RegistrarConfig { next_free_para_id: polkadot_primitives::v2::LOWEST_PUBLIC_ID, }, xcm_pallet: Default::default(), + nis_counterpart_balances: Default::default(), } } @@ -1466,10 +1466,10 @@ pub fn kusama_testnet_genesis( configuration: kusama::ConfigurationConfig { config: default_parachains_host_configuration(), }, - gilt: Default::default(), paras: Default::default(), xcm_pallet: Default::default(), nomination_pools: Default::default(), + nis_counterpart_balances: Default::default(), } } @@ -1629,12 +1629,12 @@ pub fn rococo_testnet_genesis( ..default_parachains_host_configuration() }, }, - gilt: Default::default(), paras: rococo_runtime::ParasConfig { paras: vec![] }, registrar: rococo_runtime::RegistrarConfig { next_free_para_id: polkadot_primitives::v2::LOWEST_PUBLIC_ID, }, xcm_pallet: Default::default(), + nis_counterpart_balances: Default::default(), } } diff --git a/node/service/src/lib.rs b/node/service/src/lib.rs index 3619d05c7592..4252474a68f5 100644 --- a/node/service/src/lib.rs +++ b/node/service/src/lib.rs @@ -95,6 +95,7 @@ pub use polkadot_client::PolkadotExecutorDispatch; pub use chain_spec::{KusamaChainSpec, PolkadotChainSpec, RococoChainSpec, WestendChainSpec}; pub use consensus_common::{block_validation::Chain, Proposal, SelectChain}; +use mmr_gadget::MmrGadget; #[cfg(feature = "full-node")] pub use polkadot_client::{ AbstractClient, Client, ClientHandle, ExecuteWithClient, FullBackend, FullClient, @@ -758,6 +759,7 @@ where { use polkadot_node_network_protocol::request_response::IncomingRequest; + let is_offchain_indexing_enabled = config.offchain_worker.indexing_enabled; let role = config.role.clone(); let force_authoring = config.force_authoring; let backoff_authoring_blocks = { @@ -943,7 +945,8 @@ where let parachains_db = open_database(&config.database)?; let approval_voting_config = ApprovalVotingConfig { - col_data: parachains_db::REAL_COLUMNS.col_approval_data, + col_approval_data: parachains_db::REAL_COLUMNS.col_approval_data, + col_session_data: parachains_db::REAL_COLUMNS.col_session_window_data, slot_duration_millis: slot_duration.as_millis() as u64, }; @@ -966,7 +969,8 @@ where }; let dispute_coordinator_config = DisputeCoordinatorConfig { - col_data: parachains_db::REAL_COLUMNS.col_dispute_coordinator_data, + col_dispute_data: parachains_db::REAL_COLUMNS.col_dispute_coordinator_data, + col_session_data: parachains_db::REAL_COLUMNS.col_session_window_data, }; let rpc_handlers = service::spawn_tasks(service::SpawnTasksParams { @@ -1150,11 +1154,12 @@ where let overseer_handle = overseer_handle.clone(); async move { - let parachain = polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::create( - &*client_clone, - overseer_handle, - parent, - ).await.map_err(|e| Box::new(e))?; + let parachain = + polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::new( + client_clone, + overseer_handle, + parent, + ); let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); @@ -1217,24 +1222,25 @@ where } else { task_manager.spawn_handle().spawn_blocking("beefy-gadget", None, gadget); } - } - // Reduce grandpa load on Kusama and test networks. This will slow down finality by - // approximately one slot duration, but will reduce load. We would like to see the impact on - // Kusama, see: https://github.com/paritytech/polkadot/issues/5464 - let gossip_duration = if chain_spec.is_versi() || - chain_spec.is_wococo() || - chain_spec.is_rococo() || - chain_spec.is_kusama() - { - Duration::from_millis(2000) - } else { - Duration::from_millis(1000) - }; + if is_offchain_indexing_enabled { + task_manager.spawn_handle().spawn_blocking( + "mmr-gadget", + None, + MmrGadget::start( + client.clone(), + backend.clone(), + sp_mmr_primitives::INDEXING_PREFIX.to_vec(), + ), + ); + } + } let config = grandpa::Config { // FIXME substrate#1578 make this available through chainspec - gossip_duration, + // Grandpa performance can be improved a bit by tuning this parameter, see: + // https://github.com/paritytech/polkadot/issues/5464 + gossip_duration: Duration::from_millis(1000), justification_period: 512, name: Some(name), observer_enabled: false, @@ -1537,7 +1543,8 @@ fn revert_chain_selection(db: Arc, hash: Hash) -> sp_blockchain::R fn revert_approval_voting(db: Arc, hash: Hash) -> sp_blockchain::Result<()> { let config = approval_voting_subsystem::Config { - col_data: parachains_db::REAL_COLUMNS.col_approval_data, + col_approval_data: parachains_db::REAL_COLUMNS.col_approval_data, + col_session_data: parachains_db::REAL_COLUMNS.col_session_window_data, slot_duration_millis: Default::default(), }; diff --git a/node/service/src/overseer.rs b/node/service/src/overseer.rs index a8ce3e5eaaf0..7dff86693827 100644 --- a/node/service/src/overseer.rs +++ b/node/service/src/overseer.rs @@ -129,7 +129,7 @@ where /// Obtain a prepared `OverseerBuilder`, that is initialized /// with all default values. -pub fn prepared_overseer_builder<'a, Spawner, RuntimeClient>( +pub fn prepared_overseer_builder( OverseerGenArgs { leaves, keystore, @@ -155,7 +155,7 @@ pub fn prepared_overseer_builder<'a, Spawner, RuntimeClient>( overseer_message_channel_capacity_override, req_protocol_names, peerset_protocol_names, - }: OverseerGenArgs<'a, Spawner, RuntimeClient>, + }: OverseerGenArgs, ) -> Result< InitializedOverseerBuilder< SpawnGlue, @@ -257,7 +257,7 @@ where .collator_protocol({ let side = match is_collator { IsCollator::Yes(collator_pair) => ProtocolSide::Collator( - network_service.local_peer_id().clone(), + network_service.local_peer_id(), collator_pair, collation_req_receiver, Metrics::register(registry)?, @@ -334,10 +334,10 @@ where /// would do. pub trait OverseerGen { /// Overwrite the full generation of the overseer, including the subsystems. - fn generate<'a, Spawner, RuntimeClient>( + fn generate( &self, connector: OverseerConnector, - args: OverseerGenArgs<'a, Spawner, RuntimeClient>, + args: OverseerGenArgs, ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, @@ -358,10 +358,10 @@ use polkadot_overseer::KNOWN_LEAVES_CACHE_SIZE; pub struct RealOverseerGen; impl OverseerGen for RealOverseerGen { - fn generate<'a, Spawner, RuntimeClient>( + fn generate( &self, connector: OverseerConnector, - args: OverseerGenArgs<'a, Spawner, RuntimeClient>, + args: OverseerGenArgs, ) -> Result<(Overseer, Arc>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, diff --git a/node/service/src/parachains_db/mod.rs b/node/service/src/parachains_db/mod.rs index de12a8ac1a32..74e7e13dc657 100644 --- a/node/service/src/parachains_db/mod.rs +++ b/node/service/src/parachains_db/mod.rs @@ -23,6 +23,7 @@ mod upgrade; const LOG_TARGET: &str = "parachain::db"; +/// Column configuration per version. #[cfg(any(test, feature = "full-node"))] pub(crate) mod columns { pub mod v0 { @@ -31,12 +32,17 @@ pub(crate) mod columns { pub mod v1 { pub const NUM_COLUMNS: u32 = 5; + } + pub mod v2 { + pub const NUM_COLUMNS: u32 = 6; pub const COL_AVAILABILITY_DATA: u32 = 0; pub const COL_AVAILABILITY_META: u32 = 1; pub const COL_APPROVAL_DATA: u32 = 2; pub const COL_CHAIN_SELECTION_DATA: u32 = 3; pub const COL_DISPUTE_COORDINATOR_DATA: u32 = 4; + pub const COL_SESSION_WINDOW_DATA: u32 = 5; + pub const ORDERED_COL: &[u32] = &[COL_AVAILABILITY_META, COL_CHAIN_SELECTION_DATA, COL_DISPUTE_COORDINATOR_DATA]; } @@ -56,16 +62,19 @@ pub struct ColumnsConfig { pub col_chain_selection_data: u32, /// The column used by dispute coordinator for data. pub col_dispute_coordinator_data: u32, + /// The column used for session window data. + pub col_session_window_data: u32, } /// The real columns used by the parachains DB. #[cfg(any(test, feature = "full-node"))] pub const REAL_COLUMNS: ColumnsConfig = ColumnsConfig { - col_availability_data: columns::v1::COL_AVAILABILITY_DATA, - col_availability_meta: columns::v1::COL_AVAILABILITY_META, - col_approval_data: columns::v1::COL_APPROVAL_DATA, - col_chain_selection_data: columns::v1::COL_CHAIN_SELECTION_DATA, - col_dispute_coordinator_data: columns::v1::COL_DISPUTE_COORDINATOR_DATA, + col_availability_data: columns::v2::COL_AVAILABILITY_DATA, + col_availability_meta: columns::v2::COL_AVAILABILITY_META, + col_approval_data: columns::v2::COL_APPROVAL_DATA, + col_chain_selection_data: columns::v2::COL_CHAIN_SELECTION_DATA, + col_dispute_coordinator_data: columns::v2::COL_DISPUTE_COORDINATOR_DATA, + col_session_window_data: columns::v2::COL_SESSION_WINDOW_DATA, }; #[derive(PartialEq)] @@ -83,11 +92,18 @@ pub struct CacheSizes { pub availability_meta: usize, /// Cache used by approval data. pub approval_data: usize, + /// Cache used by session window data + pub session_data: usize, } impl Default for CacheSizes { fn default() -> Self { - CacheSizes { availability_data: 25, availability_meta: 1, approval_data: 5 } + CacheSizes { + availability_data: 25, + availability_meta: 1, + approval_data: 5, + session_data: 1, + } } } @@ -106,17 +122,20 @@ pub fn open_creating_rocksdb( let path = root.join("parachains").join("db"); - let mut db_config = DatabaseConfig::with_columns(columns::v1::NUM_COLUMNS); + let mut db_config = DatabaseConfig::with_columns(columns::v2::NUM_COLUMNS); let _ = db_config .memory_budget - .insert(columns::v1::COL_AVAILABILITY_DATA, cache_sizes.availability_data); + .insert(columns::v2::COL_AVAILABILITY_DATA, cache_sizes.availability_data); + let _ = db_config + .memory_budget + .insert(columns::v2::COL_AVAILABILITY_META, cache_sizes.availability_meta); let _ = db_config .memory_budget - .insert(columns::v1::COL_AVAILABILITY_META, cache_sizes.availability_meta); + .insert(columns::v2::COL_APPROVAL_DATA, cache_sizes.approval_data); let _ = db_config .memory_budget - .insert(columns::v1::COL_APPROVAL_DATA, cache_sizes.approval_data); + .insert(columns::v2::COL_SESSION_WINDOW_DATA, cache_sizes.session_data); let path_str = path .to_str() @@ -127,7 +146,7 @@ pub fn open_creating_rocksdb( let db = Database::open(&db_config, &path_str)?; let db = polkadot_node_subsystem_util::database::kvdb_impl::DbAdapter::new( db, - columns::v1::ORDERED_COL, + columns::v2::ORDERED_COL, ); Ok(Arc::new(db)) @@ -147,12 +166,12 @@ pub fn open_creating_paritydb( std::fs::create_dir_all(&path_str)?; upgrade::try_upgrade_db(&path, DatabaseKind::ParityDB)?; - let db = parity_db::Db::open_or_create(&upgrade::paritydb_version_1_config(&path)) + let db = parity_db::Db::open_or_create(&upgrade::paritydb_version_2_config(&path)) .map_err(|err| io::Error::new(io::ErrorKind::Other, format!("{:?}", err)))?; let db = polkadot_node_subsystem_util::database::paritydb_impl::DbAdapter::new( db, - columns::v1::ORDERED_COL, + columns::v2::ORDERED_COL, ); Ok(Arc::new(db)) } diff --git a/node/service/src/parachains_db/upgrade.rs b/node/service/src/parachains_db/upgrade.rs index 73321ae04c09..01d4fb62f7f6 100644 --- a/node/service/src/parachains_db/upgrade.rs +++ b/node/service/src/parachains_db/upgrade.rs @@ -28,7 +28,7 @@ type Version = u32; const VERSION_FILE_NAME: &'static str = "parachain_db_version"; /// Current db version. -const CURRENT_VERSION: Version = 1; +const CURRENT_VERSION: Version = 2; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -36,7 +36,7 @@ pub enum Error { Io(#[from] io::Error), #[error("The version file format is incorrect")] CorruptedVersionFile, - #[error("Future version (expected {current:?}, found {got:?})")] + #[error("Parachains DB has a future version (expected {current:?}, found {got:?})")] FutureVersion { current: Version, got: Version }, } @@ -56,6 +56,8 @@ pub(crate) fn try_upgrade_db(db_path: &Path, db_kind: DatabaseKind) -> Result<() match get_db_version(db_path)? { // 0 -> 1 migration Some(0) => migrate_from_version_0_to_1(db_path, db_kind)?, + // 1 -> 2 migration + Some(1) => migrate_from_version_1_to_2(db_path, db_kind)?, // Already at current version, do nothing. Some(CURRENT_VERSION) => (), // This is an arbitrary future version, we don't handle it. @@ -112,6 +114,19 @@ fn migrate_from_version_0_to_1(path: &Path, db_kind: DatabaseKind) -> Result<(), }) } +fn migrate_from_version_1_to_2(path: &Path, db_kind: DatabaseKind) -> Result<(), Error> { + gum::info!(target: LOG_TARGET, "Migrating parachains db from version 1 to version 2 ..."); + + match db_kind { + DatabaseKind::ParityDB => paritydb_migrate_from_version_1_to_2(path), + DatabaseKind::RocksDB => rocksdb_migrate_from_version_1_to_2(path), + } + .and_then(|result| { + gum::info!(target: LOG_TARGET, "Migration complete! "); + Ok(result) + }) +} + /// Migration from version 0 to version 1: /// * the number of columns has changed from 3 to 5; fn rocksdb_migrate_from_version_0_to_1(path: &Path) -> Result<(), Error> { @@ -129,6 +144,22 @@ fn rocksdb_migrate_from_version_0_to_1(path: &Path) -> Result<(), Error> { Ok(()) } +/// Migration from version 1 to version 2: +/// * the number of columns has changed from 5 to 6; +fn rocksdb_migrate_from_version_1_to_2(path: &Path) -> Result<(), Error> { + use kvdb_rocksdb::{Database, DatabaseConfig}; + + let db_path = path + .to_str() + .ok_or_else(|| super::other_io_error("Invalid database path".into()))?; + let db_cfg = DatabaseConfig::with_columns(super::columns::v1::NUM_COLUMNS); + let mut db = Database::open(&db_cfg, db_path)?; + + db.add_column()?; + + Ok(()) +} + // This currently clears columns which had their configs altered between versions. // The columns to be changed are constrained by the `allowed_columns` vector. fn paritydb_fix_columns( @@ -190,7 +221,18 @@ fn paritydb_fix_columns( pub(crate) fn paritydb_version_1_config(path: &Path) -> parity_db::Options { let mut options = parity_db::Options::with_columns(&path, super::columns::v1::NUM_COLUMNS as u8); - for i in columns::v1::ORDERED_COL { + for i in columns::v2::ORDERED_COL { + options.columns[*i as usize].btree_index = true; + } + + options +} + +/// Database configuration for version 2. +pub(crate) fn paritydb_version_2_config(path: &Path) -> parity_db::Options { + let mut options = + parity_db::Options::with_columns(&path, super::columns::v2::NUM_COLUMNS as u8); + for i in columns::v2::ORDERED_COL { options.columns[*i as usize].btree_index = true; } @@ -202,8 +244,8 @@ pub(crate) fn paritydb_version_1_config(path: &Path) -> parity_db::Options { pub(crate) fn paritydb_version_0_config(path: &Path) -> parity_db::Options { let mut options = parity_db::Options::with_columns(&path, super::columns::v1::NUM_COLUMNS as u8); - options.columns[super::columns::v1::COL_AVAILABILITY_META as usize].btree_index = true; - options.columns[super::columns::v1::COL_CHAIN_SELECTION_DATA as usize].btree_index = true; + options.columns[super::columns::v2::COL_AVAILABILITY_META as usize].btree_index = true; + options.columns[super::columns::v2::COL_CHAIN_SELECTION_DATA as usize].btree_index = true; options } @@ -218,17 +260,30 @@ fn paritydb_migrate_from_version_0_to_1(path: &Path) -> Result<(), Error> { paritydb_fix_columns( path, paritydb_version_1_config(path), - vec![super::columns::v1::COL_DISPUTE_COORDINATOR_DATA], + vec![super::columns::v2::COL_DISPUTE_COORDINATOR_DATA], )?; Ok(()) } +/// Migration from version 1 to version 2: +/// - add a new column for session information storage +fn paritydb_migrate_from_version_1_to_2(path: &Path) -> Result<(), Error> { + let mut options = paritydb_version_1_config(path); + + // Adds the session info column. + parity_db::Db::add_column(&mut options, Default::default()) + .map_err(|e| other_io_error(format!("Error adding column {:?}", e)))?; + + Ok(()) +} + #[cfg(test)] mod tests { + use super::{columns::v2::*, *}; + #[test] - fn test_paritydb_migrate_0_1() { - use super::{columns::v1::*, *}; + fn test_paritydb_migrate_0_to_1() { use parity_db::Db; let db_dir = tempfile::tempdir().unwrap(); @@ -246,13 +301,119 @@ mod tests { try_upgrade_db(&path, DatabaseKind::ParityDB).unwrap(); let db = Db::open(&paritydb_version_1_config(&path)).unwrap(); + assert_eq!(db.get(COL_DISPUTE_COORDINATOR_DATA as u8, b"1234").unwrap(), None); assert_eq!( - db.get(super::columns::v1::COL_DISPUTE_COORDINATOR_DATA as u8, b"1234").unwrap(), - None + db.get(COL_AVAILABILITY_META as u8, b"5678").unwrap(), + Some("somevalue".as_bytes().to_vec()) ); + } + + #[test] + fn test_paritydb_migrate_1_to_2() { + use parity_db::Db; + + let db_dir = tempfile::tempdir().unwrap(); + let path = db_dir.path(); + + // We need to properly set db version for upgrade to work. + fs::write(version_file_path(path), "1").expect("Failed to write DB version"); + + { + let db = Db::open_or_create(&paritydb_version_1_config(&path)).unwrap(); + + // Write some dummy data + db.commit(vec![( + COL_DISPUTE_COORDINATOR_DATA as u8, + b"1234".to_vec(), + Some(b"somevalue".to_vec()), + )]) + .unwrap(); + + assert_eq!(db.num_columns(), columns::v1::NUM_COLUMNS as u8); + } + + try_upgrade_db(&path, DatabaseKind::ParityDB).unwrap(); + + let db = Db::open(&paritydb_version_2_config(&path)).unwrap(); + + assert_eq!(db.num_columns(), columns::v2::NUM_COLUMNS as u8); + assert_eq!( - db.get(super::columns::v1::COL_AVAILABILITY_META as u8, b"5678").unwrap(), + db.get(COL_DISPUTE_COORDINATOR_DATA as u8, b"1234").unwrap(), Some("somevalue".as_bytes().to_vec()) ); + + // Test we can write the new column. + db.commit(vec![( + COL_SESSION_WINDOW_DATA as u8, + b"1337".to_vec(), + Some(b"0xdeadb00b".to_vec()), + )]) + .unwrap(); + + // Read back data from new column. + assert_eq!( + db.get(COL_SESSION_WINDOW_DATA as u8, b"1337").unwrap(), + Some("0xdeadb00b".as_bytes().to_vec()) + ); + } + + #[test] + fn test_rocksdb_migrate_1_to_2() { + use kvdb::{DBKey, DBOp}; + use kvdb_rocksdb::{Database, DatabaseConfig}; + use polkadot_node_subsystem_util::database::{ + kvdb_impl::DbAdapter, DBTransaction, KeyValueDB, + }; + + let db_dir = tempfile::tempdir().unwrap(); + let db_path = db_dir.path().to_str().unwrap(); + let db_cfg = DatabaseConfig::with_columns(super::columns::v1::NUM_COLUMNS); + let db = Database::open(&db_cfg, db_path).unwrap(); + assert_eq!(db.num_columns(), super::columns::v1::NUM_COLUMNS as u32); + + // We need to properly set db version for upgrade to work. + fs::write(version_file_path(db_dir.path()), "1").expect("Failed to write DB version"); + { + let db = DbAdapter::new(db, columns::v2::ORDERED_COL); + db.write(DBTransaction { + ops: vec![DBOp::Insert { + col: COL_DISPUTE_COORDINATOR_DATA, + key: DBKey::from_slice(b"1234"), + value: b"0xdeadb00b".to_vec(), + }], + }) + .unwrap(); + } + + try_upgrade_db(&db_dir.path(), DatabaseKind::RocksDB).unwrap(); + + let db_cfg = DatabaseConfig::with_columns(super::columns::v2::NUM_COLUMNS); + let db = Database::open(&db_cfg, db_path).unwrap(); + + assert_eq!(db.num_columns(), super::columns::v2::NUM_COLUMNS); + + let db = DbAdapter::new(db, columns::v2::ORDERED_COL); + + assert_eq!( + db.get(COL_DISPUTE_COORDINATOR_DATA, b"1234").unwrap(), + Some("0xdeadb00b".as_bytes().to_vec()) + ); + + // Test we can write the new column. + db.write(DBTransaction { + ops: vec![DBOp::Insert { + col: COL_SESSION_WINDOW_DATA, + key: DBKey::from_slice(b"1337"), + value: b"0xdeadb00b".to_vec(), + }], + }) + .unwrap(); + + // Read back data from new column. + assert_eq!( + db.get(COL_SESSION_WINDOW_DATA, b"1337").unwrap(), + Some("0xdeadb00b".as_bytes().to_vec()) + ); } } diff --git a/node/service/src/relay_chain_selection.rs b/node/service/src/relay_chain_selection.rs index df3e68cc7b1a..890e4c16ec8f 100644 --- a/node/service/src/relay_chain_selection.rs +++ b/node/service/src/relay_chain_selection.rs @@ -343,12 +343,11 @@ where // The Chain Selection subsystem is supposed to treat the finalized // block as the best leaf in the case that there are no viable // leaves, so this should not happen in practice. - let best_leaf = self + let best_leaf = *self .leaves() .await? .first() - .ok_or_else(|| ConsensusError::Other(Box::new(Error::EmptyLeaves)))? - .clone(); + .ok_or_else(|| ConsensusError::Other(Box::new(Error::EmptyLeaves)))?; gum::trace!(target: LOG_TARGET, ?best_leaf, "Best chain"); diff --git a/node/subsystem-test-helpers/Cargo.toml b/node/subsystem-test-helpers/Cargo.toml index 2a3e5e8123d1..30b41a1a4dd3 100644 --- a/node/subsystem-test-helpers/Cargo.toml +++ b/node/subsystem-test-helpers/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "polkadot-node-subsystem-test-helpers" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" description = "Subsystem traits and message definitions" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] async-trait = "0.1.57" @@ -12,11 +12,11 @@ parking_lot = "0.12.0" polkadot-node-subsystem = { path = "../subsystem" } polkadot-node-subsystem-util = { path = "../subsystem-util" } polkadot-primitives = { path = "../../primitives" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [dev-dependencies] polkadot-overseer = { path = "../overseer" } diff --git a/node/subsystem-test-helpers/src/lib.rs b/node/subsystem-test-helpers/src/lib.rs index 79f833b7558c..dd207039091a 100644 --- a/node/subsystem-test-helpers/src/lib.rs +++ b/node/subsystem-test-helpers/src/lib.rs @@ -177,7 +177,7 @@ where /// A test subsystem context. pub struct TestSubsystemContext { tx: TestSubsystemSender, - rx: SingleItemStream>, + rx: mpsc::Receiver>, spawn: S, } @@ -239,7 +239,7 @@ pub struct TestSubsystemContextHandle { /// /// Useful for shared ownership situations (one can have multiple senders, but only one /// receiver. - pub tx: SingleItemSink>, + pub tx: mpsc::Sender>, /// Direct access to the receiver. pub rx: mpsc::UnboundedReceiver, @@ -280,11 +280,22 @@ impl TestSubsystemContextHandle { } } -/// Make a test subsystem context. +/// Make a test subsystem context with `buffer_size == 0`. This is used by most +/// of the tests. pub fn make_subsystem_context( spawner: S, ) -> (TestSubsystemContext>, TestSubsystemContextHandle) { - let (overseer_tx, overseer_rx) = single_item_sink(); + make_buffered_subsystem_context(spawner, 0) +} + +/// Make a test subsystem context with buffered overseer channel. Some tests (e.g. +/// `dispute-coordinator`) create too many parallel operations and deadlock unless +/// the channel is buffered. Usually `buffer_size=1` is enough. +pub fn make_buffered_subsystem_context( + spawner: S, + buffer_size: usize, +) -> (TestSubsystemContext>, TestSubsystemContextHandle) { + let (overseer_tx, overseer_rx) = mpsc::channel(buffer_size); let (all_messages_tx, all_messages_rx) = mpsc::unbounded(); ( diff --git a/node/subsystem-types/Cargo.toml b/node/subsystem-types/Cargo.toml index 3dfc5041702a..2f5c82be3757 100644 --- a/node/subsystem-types/Cargo.toml +++ b/node/subsystem-types/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "polkadot-node-subsystem-types" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" description = "Subsystem traits and message definitions" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] derive_more = "0.99.17" @@ -14,11 +14,11 @@ polkadot-node-network-protocol = { path = "../network/protocol" } polkadot-statement-table = { path = "../../statement-table" } polkadot-node-jaeger = { path = "../jaeger" } orchestra = "0.0.2" -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } smallvec = "1.8.0" -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } thiserror = "1.0.31" async-trait = "0.1.57" diff --git a/node/subsystem-types/src/errors.rs b/node/subsystem-types/src/errors.rs index 27c4fcdf8d37..48829e7fc779 100644 --- a/node/subsystem-types/src/errors.rs +++ b/node/subsystem-types/src/errors.rs @@ -79,7 +79,12 @@ pub enum RecoveryError { impl std::fmt::Display for RecoveryError { fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { - write!(f, "{}", self) + let msg = match self { + RecoveryError::Invalid => "Invalid", + RecoveryError::Unavailable => "Unavailable", + }; + + write!(f, "{}", msg) } } diff --git a/node/subsystem-types/src/messages.rs b/node/subsystem-types/src/messages.rs index 6e4983813984..94562ae6baef 100644 --- a/node/subsystem-types/src/messages.rs +++ b/node/subsystem-types/src/messages.rs @@ -268,13 +268,13 @@ pub enum DisputeCoordinatorMessage { /// - or the imported statements are backing/approval votes, which are always accepted. pending_confirmation: Option>, }, - /// Fetch a list of all recent disputes the co-ordinator is aware of. + /// Fetch a list of all recent disputes the coordinator is aware of. /// These are disputes which have occurred any time in recent sessions, /// and which may have already concluded. RecentDisputes(oneshot::Sender>), /// Fetch a list of all active disputes that the coordinator is aware of. /// These disputes are either not yet concluded or recently concluded. - ActiveDisputes(oneshot::Sender>), + ActiveDisputes(oneshot::Sender>), /// Get candidate votes for a candidate. QueryCandidateVotes( Vec<(SessionIndex, CandidateHash)>, @@ -541,9 +541,7 @@ pub enum AvailabilityStoreMessage { impl AvailabilityStoreMessage { /// In fact, none of the `AvailabilityStore` messages assume a particular relay parent. pub fn relay_parent(&self) -> Option { - match self { - _ => None, - } + None } } diff --git a/node/subsystem-types/src/messages/network_bridge_event.rs b/node/subsystem-types/src/messages/network_bridge_event.rs index 5abad8a3c22c..06654153357a 100644 --- a/node/subsystem-types/src/messages/network_bridge_event.rs +++ b/node/subsystem-types/src/messages/network_bridge_event.rs @@ -86,24 +86,19 @@ impl NetworkBridgeEvent { { Ok(match *self { NetworkBridgeEvent::PeerMessage(ref peer, ref msg) => - NetworkBridgeEvent::PeerMessage(peer.clone(), T::try_from(msg)?), + NetworkBridgeEvent::PeerMessage(*peer, T::try_from(msg)?), NetworkBridgeEvent::PeerConnected( ref peer, ref role, ref version, ref authority_id, - ) => NetworkBridgeEvent::PeerConnected( - peer.clone(), - role.clone(), - *version, - authority_id.clone(), - ), + ) => NetworkBridgeEvent::PeerConnected(*peer, *role, *version, authority_id.clone()), NetworkBridgeEvent::PeerDisconnected(ref peer) => - NetworkBridgeEvent::PeerDisconnected(peer.clone()), + NetworkBridgeEvent::PeerDisconnected(*peer), NetworkBridgeEvent::NewGossipTopology(ref topology) => NetworkBridgeEvent::NewGossipTopology(topology.clone()), NetworkBridgeEvent::PeerViewChange(ref peer, ref view) => - NetworkBridgeEvent::PeerViewChange(peer.clone(), view.clone()), + NetworkBridgeEvent::PeerViewChange(*peer, view.clone()), NetworkBridgeEvent::OurViewChange(ref view) => NetworkBridgeEvent::OurViewChange(view.clone()), }) diff --git a/node/subsystem-util/Cargo.toml b/node/subsystem-util/Cargo.toml index ec866746663f..6460ea6c7659 100644 --- a/node/subsystem-util/Cargo.toml +++ b/node/subsystem-util/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "polkadot-node-subsystem-util" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" description = "Subsystem traits and message definitions" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] async-trait = "0.1.57" @@ -28,13 +28,12 @@ polkadot-node-primitives = { path = "../primitives" } polkadot-overseer = { path = "../overseer" } metered = { package = "prioritized-metered-channel", version = "0.2.0" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } -kvdb = "0.12.0" -parity-util-mem = { version = "0.12.0", default-features = false } -parity-db = { version = "0.3.13" } +kvdb = "0.13.0" +parity-db = { version = "0.4.2"} [dev-dependencies] assert_matches = "1.4.0" @@ -44,5 +43,6 @@ log = "0.4.17" polkadot-node-subsystem-test-helpers = { path = "../subsystem-test-helpers" } lazy_static = "1.4.0" polkadot-primitives-test-helpers = { path = "../../primitives/test-helpers" } -kvdb-shared-tests = "0.10.0" +kvdb-shared-tests = "0.11.0" tempfile = "3.1.0" +kvdb-memorydb = "0.13.0" diff --git a/node/subsystem-util/src/database.rs b/node/subsystem-util/src/database.rs index 6f338b5d6440..d29a4460ea7e 100644 --- a/node/subsystem-util/src/database.rs +++ b/node/subsystem-util/src/database.rs @@ -29,7 +29,6 @@ pub trait Database: KeyValueDB { pub mod kvdb_impl { use super::{DBKeyValue, DBTransaction, DBValue, Database, KeyValueDB}; use kvdb::{DBOp, IoStats, IoStatsKind}; - use parity_util_mem::{MallocSizeOf, MallocSizeOfOps}; use std::{collections::BTreeSet, io::Result}; /// Adapter implementing subsystem database @@ -123,13 +122,6 @@ pub mod kvdb_impl { self.db.has_prefix(col, prefix) } } - - impl MallocSizeOf for DbAdapter { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - // ignore filter set - self.db.size_of(ops) - } - } } /// Utilities for using parity-db database. @@ -160,12 +152,6 @@ pub mod paritydb_impl { write_lock: Arc>, } - impl parity_util_mem::MallocSizeOf for DbAdapter { - fn size_of(&self, _ops: &mut parity_util_mem::MallocSizeOfOps) -> usize { - unimplemented!("size_of is not supported for parity_db") - } - } - impl KeyValueDB for DbAdapter { fn transaction(&self) -> DBTransaction { DBTransaction::new() diff --git a/node/subsystem-util/src/rolling_session_window.rs b/node/subsystem-util/src/rolling_session_window.rs index 0ff2dc6deb13..4ebfad405b5b 100644 --- a/node/subsystem-util/src/rolling_session_window.rs +++ b/node/subsystem-util/src/rolling_session_window.rs @@ -19,8 +19,13 @@ //! This is useful for consensus components which need to stay up-to-date about recent sessions but don't //! care about the state of particular blocks. +use super::database::{DBTransaction, Database}; +use kvdb::{DBKey, DBOp}; + +use parity_scale_codec::{Decode, Encode}; pub use polkadot_node_primitives::{new_session_window_size, SessionWindowSize}; use polkadot_primitives::v2::{BlockNumber, Hash, SessionIndex, SessionInfo}; +use std::sync::Arc; use futures::channel::oneshot; use polkadot_node_subsystem::{ @@ -29,7 +34,11 @@ use polkadot_node_subsystem::{ overseer, }; +// The window size is equal to the `approval-voting` and `dispute-coordinator` constants that +// have been obsoleted. +const SESSION_WINDOW_SIZE: SessionWindowSize = new_session_window_size!(6); const LOG_TARGET: &str = "parachain::rolling-session-window"; +const STORED_ROLLING_SESSION_WINDOW: &[u8] = b"Rolling_session_window"; /// Sessions unavailable in state to cache. #[derive(Debug, Clone, thiserror::Error)] @@ -94,55 +103,176 @@ pub enum SessionWindowUpdate { Unchanged, } +/// A structure to store rolling session database parameters. +#[derive(Clone)] +pub struct DatabaseParams { + /// Database reference. + pub db: Arc, + /// The column which stores the rolling session info. + pub db_column: u32, +} /// A rolling window of sessions and cached session info. pub struct RollingSessionWindow { earliest_session: SessionIndex, session_info: Vec, window_size: SessionWindowSize, + // The option is just to enable some approval-voting tests to force feed sessions + // in the window without dealing with the DB. + db_params: Option, +} + +/// The rolling session data we persist in the database. +#[derive(Encode, Decode, Default)] +struct StoredWindow { + earliest_session: SessionIndex, + session_info: Vec, } impl RollingSessionWindow { /// Initialize a new session info cache with the given window size. + /// Invariant: The database always contains the earliest session. Then, + /// we can always extend the session info vector using chain state. pub async fn new( mut sender: Sender, - window_size: SessionWindowSize, block_hash: Hash, + db_params: DatabaseParams, ) -> Result where Sender: overseer::SubsystemSender + overseer::SubsystemSender, { + // At first, determine session window start using the chain state. let session_index = get_session_index_for_child(&mut sender, block_hash).await?; let earliest_non_finalized_block_session = Self::earliest_non_finalized_block_session(&mut sender).await?; // This will increase the session window to cover the full unfinalized chain. - let window_start = std::cmp::min( - session_index.saturating_sub(window_size.get() - 1), + let on_chain_window_start = std::cmp::min( + session_index.saturating_sub(SESSION_WINDOW_SIZE.get() - 1), earliest_non_finalized_block_session, ); - match load_all_sessions(&mut sender, block_hash, window_start, session_index).await { - Err(kind) => Err(SessionsUnavailable { - kind, - info: Some(SessionsUnavailableInfo { - window_start, - window_end: session_index, - block_hash, + // Fetch session information from DB. + let maybe_stored_window = Self::db_load(db_params.clone()); + + // Get the DB stored sessions and recompute window start based on DB data. + let (mut window_start, stored_sessions) = + if let Some(mut stored_window) = maybe_stored_window { + // Check if DB is ancient. + if earliest_non_finalized_block_session > + stored_window.earliest_session + stored_window.session_info.len() as u32 + { + // If ancient, we scrap it and fetch from chain state. + stored_window.session_info.clear(); + } + + // The session window might extend beyond the last finalized block, but that's fine as we'll prune it at + // next update. + let window_start = if stored_window.session_info.len() > 0 { + // If there is at least one entry in db, we always take the DB as source of truth. + stored_window.earliest_session + } else { + on_chain_window_start + }; + + (window_start, stored_window.session_info) + } else { + (on_chain_window_start, Vec::new()) + }; + + // Compute the amount of sessions missing from the window that will be fetched from chain state. + let sessions_missing_count = session_index + .saturating_sub(window_start) + .saturating_add(1) + .saturating_sub(stored_sessions.len() as u32); + + // Extend from chain state. + let sessions = if sessions_missing_count > 0 { + match extend_sessions_from_chain_state( + stored_sessions, + &mut sender, + block_hash, + &mut window_start, + session_index, + ) + .await + { + Err(kind) => Err(SessionsUnavailable { + kind, + info: Some(SessionsUnavailableInfo { + window_start, + window_end: session_index, + block_hash, + }), }), - }), - Ok(s) => Ok(Self { earliest_session: window_start, session_info: s, window_size }), + Ok(sessions) => Ok(sessions), + }? + } else { + // There are no new sessions to be fetched from chain state. + Vec::new() + }; + + Ok(Self { + earliest_session: window_start, + session_info: sessions, + window_size: SESSION_WINDOW_SIZE, + db_params: Some(db_params), + }) + } + + // Load session information from the parachains db. + fn db_load(db_params: DatabaseParams) -> Option { + match db_params.db.get(db_params.db_column, STORED_ROLLING_SESSION_WINDOW).ok()? { + None => None, + Some(raw) => { + let maybe_decoded = StoredWindow::decode(&mut &raw[..]).map(Some); + match maybe_decoded { + Ok(decoded) => decoded, + Err(err) => { + gum::warn!( + target: LOG_TARGET, + ?err, + "Failed decoding db entry; will start with onchain session infos and self-heal DB entry on next update." + ); + None + }, + } + }, + } + } + + // Saves/Updates all sessions in the database. + // TODO: https://github.com/paritytech/polkadot/issues/6144 + fn db_save(&mut self, stored_window: StoredWindow) { + if let Some(db_params) = self.db_params.as_ref() { + match db_params.db.write(DBTransaction { + ops: vec![DBOp::Insert { + col: db_params.db_column, + key: DBKey::from_slice(STORED_ROLLING_SESSION_WINDOW), + value: stored_window.encode(), + }], + }) { + Ok(_) => {}, + Err(err) => { + gum::warn!(target: LOG_TARGET, ?err, "Failed writing db entry"); + }, + } } } /// Initialize a new session info cache with the given window size and /// initial data. + /// This is only used in `approval voting` tests. pub fn with_session_info( - window_size: SessionWindowSize, earliest_session: SessionIndex, session_info: Vec, ) -> Self { - RollingSessionWindow { earliest_session, session_info, window_size } + RollingSessionWindow { + earliest_session, + session_info, + window_size: SESSION_WINDOW_SIZE, + db_params: None, + } } /// Access the session info for the given session index, if stored within the window. @@ -164,6 +294,11 @@ impl RollingSessionWindow { self.earliest_session + (self.session_info.len() as SessionIndex).saturating_sub(1) } + /// Returns `true` if `session_index` is contained in the window. + pub fn contains(&self, session_index: SessionIndex) -> bool { + session_index >= self.earliest_session() && session_index <= self.latest_session() + } + async fn earliest_non_finalized_block_session( sender: &mut Sender, ) -> Result @@ -262,11 +397,6 @@ impl RollingSessionWindow { + overseer::SubsystemSender, { let session_index = get_session_index_for_child(sender, block_hash).await?; - let earliest_non_finalized_block_session = - Self::earliest_non_finalized_block_session(sender).await?; - - let old_window_start = self.earliest_session; - let latest = self.latest_session(); // Either cached or ancient. @@ -274,6 +404,10 @@ impl RollingSessionWindow { return Ok(SessionWindowUpdate::Unchanged) } + let earliest_non_finalized_block_session = + Self::earliest_non_finalized_block_session(sender).await?; + + let old_window_start = self.earliest_session; let old_window_end = latest; // Ensure we keep sessions up to last finalized block by adjusting the window start. @@ -283,16 +417,34 @@ impl RollingSessionWindow { earliest_non_finalized_block_session, ); - // keep some of the old window, if applicable. - let overlap_start = window_start.saturating_sub(old_window_start); + // Never look back past earliest session, since if sessions beyond were not needed or available + // in the past remains valid for the future (window only advances forward). + let mut window_start = std::cmp::max(window_start, self.earliest_session); + + let mut sessions = self.session_info.clone(); + let sessions_out_of_window = window_start.saturating_sub(old_window_start) as usize; - let fresh_start = if latest < window_start { window_start } else { latest + 1 }; + let sessions = if sessions_out_of_window < sessions.len() { + // Drop sessions based on how much the window advanced. + sessions.split_off((window_start as usize).saturating_sub(old_window_start as usize)) + } else { + // Window has jumped such that we need to fetch all sessions from on chain. + Vec::new() + }; - match load_all_sessions(sender, block_hash, fresh_start, session_index).await { + match extend_sessions_from_chain_state( + sessions, + sender, + block_hash, + &mut window_start, + session_index, + ) + .await + { Err(kind) => Err(SessionsUnavailable { kind, info: Some(SessionsUnavailableInfo { - window_start: fresh_start, + window_start, window_end: session_index, block_hash, }), @@ -305,15 +457,19 @@ impl RollingSessionWindow { new_window_end: session_index, }; - let outdated = std::cmp::min(overlap_start as usize, self.session_info.len()); - self.session_info.drain(..outdated); - self.session_info.extend(s); + self.session_info = s; + // we need to account for this case: // window_start ................................... session_index // old_window_start ........... latest let new_earliest = std::cmp::max(window_start, old_window_start); self.earliest_session = new_earliest; + // Update current window in DB. + self.db_save(StoredWindow { + earliest_session: self.earliest_session, + session_info: self.session_info.clone(), + }); Ok(update) }, } @@ -354,13 +510,23 @@ async fn get_session_index_for_child( } } -async fn load_all_sessions( +/// Attempts to extend db stored sessions with sessions missing between `start` and up to `end_inclusive`. +/// Runtime session info fetching errors are ignored if that doesn't create a gap in the window. +async fn extend_sessions_from_chain_state( + stored_sessions: Vec, sender: &mut impl overseer::SubsystemSender, block_hash: Hash, - start: SessionIndex, + window_start: &mut SessionIndex, end_inclusive: SessionIndex, ) -> Result, SessionsUnavailableReason> { - let mut v = Vec::new(); + // Start from the db sessions. + let mut sessions = stored_sessions; + // We allow session fetch failures only if we won't create a gap in the window by doing so. + // If `allow_failure` is set to true here, fetching errors are ignored until we get a first session. + let mut allow_failure = sessions.is_empty(); + + let start = *window_start + sessions.len() as u32; + for i in start..=end_inclusive { let (tx, rx) = oneshot::channel(); sender @@ -370,22 +536,58 @@ async fn load_all_sessions( )) .await; - let session_info = match rx.await { - Ok(Ok(Some(s))) => s, - Ok(Ok(None)) => return Err(SessionsUnavailableReason::Missing(i)), - Ok(Err(e)) => return Err(SessionsUnavailableReason::RuntimeApi(e)), - Err(canceled) => return Err(SessionsUnavailableReason::RuntimeApiUnavailable(canceled)), + match rx.await { + Ok(Ok(Some(session_info))) => { + // We do not allow failure anymore after having at least 1 session in window. + allow_failure = false; + sessions.push(session_info); + }, + Ok(Ok(None)) if !allow_failure => return Err(SessionsUnavailableReason::Missing(i)), + Ok(Ok(None)) => { + // Handle `allow_failure` true. + // If we didn't get the session, we advance window start. + *window_start += 1; + gum::debug!( + target: LOG_TARGET, + session = ?i, + "Session info missing from runtime." + ); + }, + Ok(Err(e)) if !allow_failure => return Err(SessionsUnavailableReason::RuntimeApi(e)), + Err(canceled) if !allow_failure => + return Err(SessionsUnavailableReason::RuntimeApiUnavailable(canceled)), + Ok(Err(err)) => { + // Handle `allow_failure` true. + // If we didn't get the session, we advance window start. + *window_start += 1; + gum::debug!( + target: LOG_TARGET, + session = ?i, + ?err, + "Error while fetching session information." + ); + }, + Err(err) => { + // Handle `allow_failure` true. + // If we didn't get the session, we advance window start. + *window_start += 1; + gum::debug!( + target: LOG_TARGET, + session = ?i, + ?err, + "Channel error while fetching session information." + ); + }, }; - - v.push(session_info); } - Ok(v) + Ok(sessions) } #[cfg(test)] mod tests { use super::*; + use crate::database::kvdb_impl::DbAdapter; use assert_matches::assert_matches; use polkadot_node_subsystem::{ messages::{AllMessages, AvailabilityRecoveryMessage}, @@ -395,14 +597,23 @@ mod tests { use polkadot_primitives::v2::Header; use sp_core::testing::TaskExecutor; - pub const TEST_WINDOW_SIZE: SessionWindowSize = new_session_window_size!(6); + const SESSION_DATA_COL: u32 = 0; + + const NUM_COLUMNS: u32 = 1; + + fn dummy_db_params() -> DatabaseParams { + let db = kvdb_memorydb::create(NUM_COLUMNS); + let db = DbAdapter::new(db, &[]); + let db: Arc = Arc::new(db); + DatabaseParams { db, db_column: SESSION_DATA_COL } + } fn dummy_session_info(index: SessionIndex) -> SessionInfo { SessionInfo { - validators: Vec::new(), + validators: Default::default(), discovery_keys: Vec::new(), assignment_keys: Vec::new(), - validator_groups: Vec::new(), + validator_groups: Default::default(), n_cores: index as _, zeroth_delay_tranche_width: index as _, relay_vrf_modulo_samples: index as _, @@ -420,7 +631,10 @@ mod tests { session: SessionIndex, window: Option, expect_requests_from: SessionIndex, - ) { + db_params: Option, + ) -> RollingSessionWindow { + let db_params = db_params.unwrap_or(dummy_db_params()); + let header = Header { digest: Default::default(), extrinsics_root: Default::default(), @@ -448,9 +662,8 @@ mod tests { let test_fut = { Box::pin(async move { let window = match window { - None => RollingSessionWindow::new(sender.clone(), TEST_WINDOW_SIZE, hash) - .await - .unwrap(), + None => + RollingSessionWindow::new(sender.clone(), hash, db_params).await.unwrap(), Some(mut window) => { window.cache_session_info_for_head(sender, hash).await.unwrap(); window @@ -461,6 +674,8 @@ mod tests { window.session_info, (expected_start_session..=session).map(dummy_session_info).collect::>(), ); + + window }) }; @@ -522,12 +737,43 @@ mod tests { } }); - futures::executor::block_on(futures::future::join(test_fut, aux_fut)); + let (window, _) = futures::executor::block_on(futures::future::join(test_fut, aux_fut)); + window + } + + #[test] + fn cache_session_info_start_empty_db() { + let db_params = dummy_db_params(); + + let window = cache_session_info_test( + (10 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), + 10, + None, + (10 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), + Some(db_params.clone()), + ); + + let window = cache_session_info_test( + (11 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), + 11, + Some(window), + 11, + None, + ); + assert_eq!(window.session_info.len(), SESSION_WINDOW_SIZE.get() as usize); + + cache_session_info_test( + (11 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), + 12, + None, + 12, + Some(db_params), + ); } #[test] fn cache_session_info_first_early() { - cache_session_info_test(0, 1, None, 0); + cache_session_info_test(0, 1, None, 0, None); } #[test] @@ -535,19 +781,36 @@ mod tests { let window = RollingSessionWindow { earliest_session: 1, session_info: vec![dummy_session_info(1)], - window_size: TEST_WINDOW_SIZE, + window_size: SESSION_WINDOW_SIZE, + db_params: Some(dummy_db_params()), }; - cache_session_info_test(1, 2, Some(window), 2); + cache_session_info_test(1, 2, Some(window), 2, None); + } + + #[test] + fn cache_session_window_contains() { + let window = RollingSessionWindow { + earliest_session: 10, + session_info: vec![dummy_session_info(1)], + window_size: SESSION_WINDOW_SIZE, + db_params: Some(dummy_db_params()), + }; + + assert!(!window.contains(0)); + assert!(!window.contains(10 + SESSION_WINDOW_SIZE.get())); + assert!(!window.contains(11)); + assert!(!window.contains(10 + SESSION_WINDOW_SIZE.get() - 1)); } #[test] fn cache_session_info_first_late() { cache_session_info_test( - (100 as SessionIndex).saturating_sub(TEST_WINDOW_SIZE.get() - 1), + (100 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), 100, None, - (100 as SessionIndex).saturating_sub(TEST_WINDOW_SIZE.get() - 1), + (100 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), + None, ); } @@ -560,48 +823,88 @@ mod tests { dummy_session_info(51), dummy_session_info(52), ], - window_size: TEST_WINDOW_SIZE, + window_size: SESSION_WINDOW_SIZE, + db_params: Some(dummy_db_params()), }; cache_session_info_test( - (100 as SessionIndex).saturating_sub(TEST_WINDOW_SIZE.get() - 1), + (100 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), 100, Some(window), - (100 as SessionIndex).saturating_sub(TEST_WINDOW_SIZE.get() - 1), + (100 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), + None, ); } #[test] fn cache_session_info_roll_full() { - let start = 99 - (TEST_WINDOW_SIZE.get() - 1); + let start = 99 - (SESSION_WINDOW_SIZE.get() - 1); let window = RollingSessionWindow { earliest_session: start, session_info: (start..=99).map(dummy_session_info).collect(), - window_size: TEST_WINDOW_SIZE, + window_size: SESSION_WINDOW_SIZE, + db_params: Some(dummy_db_params()), }; cache_session_info_test( - (100 as SessionIndex).saturating_sub(TEST_WINDOW_SIZE.get() - 1), + (100 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), 100, Some(window), 100, // should only make one request. + None, ); } + #[test] + fn cache_session_info_roll_many_full_db() { + let db_params = dummy_db_params(); + let start = 97 - (SESSION_WINDOW_SIZE.get() - 1); + let window = RollingSessionWindow { + earliest_session: start, + session_info: (start..=97).map(dummy_session_info).collect(), + window_size: SESSION_WINDOW_SIZE, + db_params: Some(db_params.clone()), + }; + + cache_session_info_test( + (100 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), + 100, + Some(window), + 98, + None, + ); + + // We expect the session to be populated from DB, and only fetch 101 from on chain. + cache_session_info_test( + (100 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), + 101, + None, + 101, + Some(db_params.clone()), + ); + + // Session warps in the future. + let window = cache_session_info_test(195, 200, None, 195, Some(db_params)); + + assert_eq!(window.session_info.len(), SESSION_WINDOW_SIZE.get() as usize); + } + #[test] fn cache_session_info_roll_many_full() { - let start = 97 - (TEST_WINDOW_SIZE.get() - 1); + let start = 97 - (SESSION_WINDOW_SIZE.get() - 1); let window = RollingSessionWindow { earliest_session: start, session_info: (start..=97).map(dummy_session_info).collect(), - window_size: TEST_WINDOW_SIZE, + window_size: SESSION_WINDOW_SIZE, + db_params: Some(dummy_db_params()), }; cache_session_info_test( - (100 as SessionIndex).saturating_sub(TEST_WINDOW_SIZE.get() - 1), + (100 as SessionIndex).saturating_sub(SESSION_WINDOW_SIZE.get() - 1), 100, Some(window), 98, + None, ); } @@ -611,7 +914,8 @@ mod tests { let window = RollingSessionWindow { earliest_session: start, session_info: (0..=1).map(dummy_session_info).collect(), - window_size: TEST_WINDOW_SIZE, + window_size: SESSION_WINDOW_SIZE, + db_params: Some(dummy_db_params()), }; cache_session_info_test( @@ -619,6 +923,7 @@ mod tests { 2, Some(window), 2, // should only make one request. + None, ); } @@ -628,14 +933,17 @@ mod tests { let window = RollingSessionWindow { earliest_session: start, session_info: (0..=1).map(dummy_session_info).collect(), - window_size: TEST_WINDOW_SIZE, + window_size: SESSION_WINDOW_SIZE, + db_params: Some(dummy_db_params()), }; - cache_session_info_test(0, 3, Some(window), 2); + let actual_window_size = window.session_info.len() as u32; + + cache_session_info_test(0, 3, Some(window), actual_window_size, None); } #[test] - fn any_session_stretch_for_unfinalized_chain() { + fn cache_session_fails_for_gap_in_window() { // Session index of the tip of our fake test chain. let session: SessionIndex = 100; let genesis_session: SessionIndex = 0; @@ -664,7 +972,8 @@ mod tests { let test_fut = { let sender = ctx.sender().clone(); Box::pin(async move { - let res = RollingSessionWindow::new(sender, TEST_WINDOW_SIZE, hash).await; + let res = RollingSessionWindow::new(sender, hash, dummy_db_params()).await; + assert!(res.is_err()); }) }; @@ -713,6 +1022,135 @@ mod tests { ); // Unfinalized chain starts at geneisis block, so session 0 is how far we stretch. + // First 50 sessions are missing. + for i in genesis_session..=50 { + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + h, + RuntimeApiRequest::SessionInfo(j, s_tx), + )) => { + assert_eq!(h, hash); + assert_eq!(i, j); + let _ = s_tx.send(Ok(None)); + } + ); + } + // next 10 sessions are present + for i in 51..=60 { + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + h, + RuntimeApiRequest::SessionInfo(j, s_tx), + )) => { + assert_eq!(h, hash); + assert_eq!(i, j); + let _ = s_tx.send(Ok(Some(dummy_session_info(i)))); + } + ); + } + // gap of 1 session + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + h, + RuntimeApiRequest::SessionInfo(j, s_tx), + )) => { + assert_eq!(h, hash); + assert_eq!(61, j); + let _ = s_tx.send(Ok(None)); + } + ); + }); + + futures::executor::block_on(futures::future::join(test_fut, aux_fut)); + } + + #[test] + fn any_session_stretch_with_failure_allowed_for_unfinalized_chain() { + // Session index of the tip of our fake test chain. + let session: SessionIndex = 100; + let genesis_session: SessionIndex = 0; + + let header = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: 5, + state_root: Default::default(), + parent_hash: Default::default(), + }; + + let finalized_header = Header { + digest: Default::default(), + extrinsics_root: Default::default(), + number: 0, + state_root: Default::default(), + parent_hash: Default::default(), + }; + + let pool = TaskExecutor::new(); + let (mut ctx, mut handle) = make_subsystem_context::<(), _>(pool.clone()); + + let hash = header.hash(); + + let test_fut = { + let sender = ctx.sender().clone(); + Box::pin(async move { + let res = RollingSessionWindow::new(sender, hash, dummy_db_params()).await; + assert!(res.is_ok()); + let rsw = res.unwrap(); + // Since first 50 sessions are missing the earliest should be 50. + assert_eq!(rsw.earliest_session, 50); + assert_eq!(rsw.session_info.len(), 51); + }) + }; + + let aux_fut = Box::pin(async move { + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + h, + RuntimeApiRequest::SessionIndexForChild(s_tx), + )) => { + assert_eq!(h, hash); + let _ = s_tx.send(Ok(session)); + } + ); + + assert_matches!( + handle.recv().await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockNumber( + s_tx, + )) => { + let _ = s_tx.send(Ok(finalized_header.number)); + } + ); + + assert_matches!( + handle.recv().await, + AllMessages::ChainApi(ChainApiMessage::FinalizedBlockHash( + block_number, + s_tx, + )) => { + assert_eq!(block_number, finalized_header.number); + let _ = s_tx.send(Ok(Some(finalized_header.hash()))); + } + ); + + assert_matches!( + handle.recv().await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + h, + RuntimeApiRequest::SessionIndexForChild(s_tx), + )) => { + assert_eq!(h, finalized_header.hash()); + let _ = s_tx.send(Ok(0)); + } + ); + + // Unfinalized chain starts at geneisis block, so session 0 is how far we stretch. + // We also test if failure is allowed for 50 first missing sessions. for i in genesis_session..=session { assert_matches!( handle.recv().await, @@ -723,7 +1161,7 @@ mod tests { assert_eq!(h, hash); assert_eq!(i, j); - let _ = s_tx.send(Ok(if i == session { + let _ = s_tx.send(Ok(if i < 50 { None } else { Some(dummy_session_info(i)) @@ -739,7 +1177,7 @@ mod tests { #[test] fn any_session_unavailable_for_caching_means_no_change() { let session: SessionIndex = 6; - let start_session = session.saturating_sub(TEST_WINDOW_SIZE.get() - 1); + let start_session = session.saturating_sub(SESSION_WINDOW_SIZE.get() - 1); let header = Header { digest: Default::default(), @@ -765,7 +1203,7 @@ mod tests { let test_fut = { let sender = ctx.sender().clone(); Box::pin(async move { - let res = RollingSessionWindow::new(sender, TEST_WINDOW_SIZE, hash).await; + let res = RollingSessionWindow::new(sender, hash, dummy_db_params()).await; assert!(res.is_err()); }) }; @@ -857,7 +1295,7 @@ mod tests { Box::pin(async move { let sender = ctx.sender().clone(); let window = - RollingSessionWindow::new(sender, TEST_WINDOW_SIZE, hash).await.unwrap(); + RollingSessionWindow::new(sender, hash, dummy_db_params()).await.unwrap(); assert_eq!(window.earliest_session, session); assert_eq!(window.session_info, vec![dummy_session_info(session)]); diff --git a/node/subsystem-util/src/runtime/mod.rs b/node/subsystem-util/src/runtime/mod.rs index 7fcae2c57b09..5b8baad0f94f 100644 --- a/node/subsystem-util/src/runtime/mod.rs +++ b/node/subsystem-util/src/runtime/mod.rs @@ -27,9 +27,9 @@ use sp_keystore::{CryptoStore, SyncCryptoStorePtr}; use polkadot_node_subsystem::{messages::RuntimeApiMessage, overseer, SubsystemSender}; use polkadot_primitives::v2::{ - CandidateEvent, CoreState, EncodeAs, GroupIndex, GroupRotationInfo, Hash, OccupiedCore, - ScrapedOnChainVotes, SessionIndex, SessionInfo, Signed, SigningContext, UncheckedSigned, - ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + CandidateEvent, CoreState, EncodeAs, GroupIndex, GroupRotationInfo, Hash, IndexedVec, + OccupiedCore, ScrapedOnChainVotes, SessionIndex, SessionInfo, Signed, SigningContext, + UncheckedSigned, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, }; use crate::{ @@ -228,7 +228,10 @@ impl RuntimeInfo { /// Get our `ValidatorIndex`. /// /// Returns: None if we are not a validator. - async fn get_our_index(&self, validators: &[ValidatorId]) -> Option { + async fn get_our_index( + &self, + validators: &IndexedVec, + ) -> Option { let keystore = self.keystore.as_ref()?; for (i, v) in validators.iter().enumerate() { if CryptoStore::has_keys(&**keystore, &[(v.to_raw_vec(), ValidatorId::ID)]).await { @@ -254,7 +257,7 @@ where session_info .validators - .get(signed.unchecked_validator_index().0 as usize) + .get(signed.unchecked_validator_index()) .ok_or_else(|| signed.clone()) .and_then(|v| signed.try_into_checked(&signing_context, v)) } diff --git a/node/subsystem/Cargo.toml b/node/subsystem/Cargo.toml index 1d783f748b45..2d788c10b4c1 100644 --- a/node/subsystem/Cargo.toml +++ b/node/subsystem/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "polkadot-node-subsystem" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" description = "Subsystem traits and message definitions and the generated overseer" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] polkadot-overseer = { path = "../overseer" } diff --git a/node/test/client/Cargo.toml b/node/test/client/Cargo.toml index 91ba27476c04..ecafc4ab39f3 100644 --- a/node/test/client/Cargo.toml +++ b/node/test/client/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-test-client" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } @@ -14,20 +14,20 @@ polkadot-primitives = { path = "../../../primitives" } polkadot-node-subsystem = { path = "../../subsystem" } # Substrate dependencies -substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [dev-dependencies] -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures = "0.3.21" diff --git a/node/test/performance-test/Cargo.toml b/node/test/performance-test/Cargo.toml index 55d74ad62f1d..95da89662579 100644 --- a/node/test/performance-test/Cargo.toml +++ b/node/test/performance-test/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-performance-test" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] thiserror = "1.0.31" diff --git a/node/test/service/Cargo.toml b/node/test/service/Cargo.toml index a85a7db081ab..e77228562696 100644 --- a/node/test/service/Cargo.toml +++ b/node/test/service/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-test-service" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] futures = "0.3.21" @@ -10,7 +10,7 @@ hex = "0.4.3" gum = { package = "tracing-gum", path = "../../gum" } rand = "0.8.5" tempfile = "3.2.0" -tokio = "1.19.2" +tokio = "1.22.0" # Polkadot dependencies polkadot-overseer = { path = "../../overseer" } @@ -26,42 +26,42 @@ test-runtime-constants = { path = "../../../runtime/test-runtime/constants" } polkadot-runtime-parachains = { path = "../../../runtime/parachains" } # Substrate dependencies -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -babe = { package = "sc-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -grandpa_primitives = { package = "sp-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-service = { git = "https://github.com/paritytech/substrate", default-features = false, features = [ "wasmtime" ] , branch = "polkadot-v0.9.31" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +babe = { package = "sc-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +grandpa_primitives = { package = "sp-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } serde_json = "1.0.81" -substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -tokio = { version = "1.19.2", features = ["macros"] } +substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +tokio = { version = "1.22.0", features = ["macros"] } [features] runtime-metrics=["polkadot-test-runtime/runtime-metrics"] diff --git a/node/test/service/src/lib.rs b/node/test/service/src/lib.rs index 8fe31ce2b5b4..831f0c85aaaa 100644 --- a/node/test/service/src/lib.rs +++ b/node/test/service/src/lib.rs @@ -27,7 +27,7 @@ use polkadot_node_subsystem::messages::{CollationGenerationMessage, CollatorProt use polkadot_overseer::Handle; use polkadot_primitives::v2::{Balance, CollatorPair, HeadData, Id as ParaId, ValidationCode}; use polkadot_runtime_common::BlockHashCount; -use polkadot_runtime_parachains::paras::ParaGenesisArgs; +use polkadot_runtime_parachains::paras::{ParaGenesisArgs, ParaKind}; use polkadot_service::{ ClientHandle, Error, ExecuteWithClient, FullClient, IsCollator, NewFull, PrometheusConfig, }; @@ -305,7 +305,7 @@ impl PolkadotTestNode { genesis: ParaGenesisArgs { genesis_head: genesis_head.into(), validation_code: validation_code.into(), - parachain: true, + para_kind: ParaKind::Parachain, }, }; diff --git a/node/zombienet-backchannel/Cargo.toml b/node/zombienet-backchannel/Cargo.toml index 74cd56ec521a..74e6751eb7de 100644 --- a/node/zombienet-backchannel/Cargo.toml +++ b/node/zombienet-backchannel/Cargo.toml @@ -2,14 +2,14 @@ name = "zombienet-backchannel" description = "Zombienet backchannel to notify test runner and coordinate with malus actors." license = "GPL-3.0-only" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" readme = "README.md" publish = false +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] -tokio = { version = "1.19.2", default-features = false, features = ["macros", "net", "rt-multi-thread", "sync"] } +tokio = { version = "1.22.0", default-features = false, features = ["macros", "net", "rt-multi-thread", "sync"] } url = "2.0.0" tokio-tungstenite = "0.17" futures-util = "0.3.23" diff --git a/parachain/Cargo.toml b/parachain/Cargo.toml index f146ee8a778d..730976426cc0 100644 --- a/parachain/Cargo.toml +++ b/parachain/Cargo.toml @@ -1,21 +1,20 @@ [package] name = "polkadot-parachain" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Types and utilities for creating and working with parachains" -edition = "2021" +authors.workspace = true +edition.workspace = true +version.workspace = true [dependencies] # note: special care is taken to avoid inclusion of `sp-io` externals when compiling # this crate for WASM. This is critical to avoid forcing all parachain WASM into implementing # various unnecessary Substrate-specific endpoints. parity-scale-codec = { version = "3.1.5", default-features = false, features = [ "derive" ] } -parity-util-mem = { version = "0.12.0", default-features = false, optional = true } scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } polkadot-core-primitives = { path = "../core-primitives", default-features = false } derive_more = "0.99.11" @@ -32,7 +31,6 @@ std = [ "sp-std/std", "sp-runtime/std", "sp-core/std", - "parity-util-mem", "polkadot-core-primitives/std", "frame-support/std", ] diff --git a/parachain/src/primitives.rs b/parachain/src/primitives.rs index 2c18b178271f..e638b83c2d7c 100644 --- a/parachain/src/primitives.rs +++ b/parachain/src/primitives.rs @@ -31,9 +31,6 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use sp_core::bytes; -#[cfg(feature = "std")] -use parity_util_mem::MallocSizeOf; - use polkadot_core_primitives::{Hash, OutboundHrmpMessage}; /// Block number type used by the relay chain. @@ -43,7 +40,7 @@ pub use polkadot_core_primitives::BlockNumber as RelayChainBlockNumber; #[derive( PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, derive_more::From, TypeInfo, )] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, MallocSizeOf, Default))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, Default))] pub struct HeadData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec); impl HeadData { @@ -55,7 +52,7 @@ impl HeadData { /// Parachain validation code. #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, derive_more::From, TypeInfo)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))] pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec); impl ValidationCode { @@ -71,7 +68,6 @@ impl ValidationCode { /// /// This type makes it easy to enforce that a hash is a validation code hash on the type level. #[derive(Clone, Copy, Encode, Decode, Hash, Eq, PartialEq, PartialOrd, Ord, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct ValidationCodeHash(Hash); impl sp_std::fmt::Display for ValidationCodeHash { @@ -114,7 +110,7 @@ impl sp_std::fmt::LowerHex for ValidationCodeHash { /// /// Contains everything required to validate para-block, may contain block and witness data. #[derive(PartialEq, Eq, Clone, Encode, Decode, derive_more::From, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct BlockData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec); /// Unique identifier of a parachain. @@ -134,10 +130,7 @@ pub struct BlockData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec RuntimeDebug, TypeInfo, )] -#[cfg_attr( - feature = "std", - derive(serde::Serialize, serde::Deserialize, derive_more::Display, MallocSizeOf) -)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize, derive_more::Display))] pub struct Id(u32); impl TypeId for Id { diff --git a/parachain/test-parachains/Cargo.toml b/parachain/test-parachains/Cargo.toml index ae418661e313..9815c989c35c 100644 --- a/parachain/test-parachains/Cargo.toml +++ b/parachain/test-parachains/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "test-parachains" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Integration tests using the test-parachains" -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] tiny-keccak = { version = "2.0.2", features = ["keccak"] } @@ -13,7 +13,7 @@ adder = { package = "test-parachain-adder", path = "adder" } halt = { package = "test-parachain-halt", path = "halt" } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/parachain/test-parachains/adder/Cargo.toml b/parachain/test-parachains/adder/Cargo.toml index b376fc021c8a..5e238521b482 100644 --- a/parachain/test-parachains/adder/Cargo.toml +++ b/parachain/test-parachains/adder/Cargo.toml @@ -1,23 +1,23 @@ [package] name = "test-parachain-adder" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Test parachain which adds to a number as its state transition" -edition = "2021" build = "build.rs" +edition.workspace = true +version.workspace = true +authors.workspace = true [dependencies] parachain = { package = "polkadot-parachain", path = "../../", default-features = false, features = [ "wasm-api" ] } parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } tiny-keccak = { version = "2.0.2", features = ["keccak"] } dlmalloc = { version = "0.2.4", features = [ "global" ] } # We need to make sure the global allocator is disabled until we have support of full substrate externalities -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, features = [ "disable_allocator" ] , branch = "polkadot-v0.9.31" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, features = [ "disable_allocator" ] , branch = "polkadot-v0.9.36" } [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = [ "std" ] diff --git a/parachain/test-parachains/adder/collator/Cargo.toml b/parachain/test-parachains/adder/collator/Cargo.toml index c1b2335374bf..0d32d39b14ea 100644 --- a/parachain/test-parachains/adder/collator/Cargo.toml +++ b/parachain/test-parachains/adder/collator/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "test-parachain-adder-collator" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Collator for the adder test parachain" -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [[bin]] name = "adder-collator" @@ -27,9 +27,9 @@ polkadot-service = { path = "../../../../node/service", features = ["rococo-nati polkadot-node-primitives = { path = "../../../../node/primitives" } polkadot-node-subsystem = { path = "../../../../node/subsystem" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } # This one is tricky. Even though it is not used directly by the collator, we still need it for the # `puppet_worker` binary, which is required for the integration test. However, this shouldn't be @@ -40,8 +40,8 @@ polkadot-node-core-pvf = { path = "../../../../node/core/pvf" } polkadot-parachain = { path = "../../.." } polkadot-test-service = { path = "../../../../node/test/service" } -substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } -tokio = { version = "1.19.2", features = ["macros"] } +tokio = { version = "1.22.0", features = ["macros"] } diff --git a/parachain/test-parachains/halt/Cargo.toml b/parachain/test-parachains/halt/Cargo.toml index 262c6436f1b5..1261ac2ebc5c 100644 --- a/parachain/test-parachains/halt/Cargo.toml +++ b/parachain/test-parachains/halt/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "test-parachain-halt" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Test parachain which executes forever" -edition = "2021" build = "build.rs" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = [ "std" ] diff --git a/parachain/test-parachains/undying/Cargo.toml b/parachain/test-parachains/undying/Cargo.toml index 6eb7d19aae11..8a6dcf1f272c 100644 --- a/parachain/test-parachains/undying/Cargo.toml +++ b/parachain/test-parachains/undying/Cargo.toml @@ -1,24 +1,24 @@ [package] name = "test-parachain-undying" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Test parachain for zombienet integration tests" -edition = "2021" build = "build.rs" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] parachain = { package = "polkadot-parachain", path = "../../", default-features = false, features = [ "wasm-api" ] } parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } tiny-keccak = { version = "2.0.2", features = ["keccak"] } dlmalloc = { version = "0.2.4", features = [ "global" ] } log = { version = "0.4.17", default-features = false } # We need to make sure the global allocator is disabled until we have support of full substrate externalities -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, features = [ "disable_allocator" ] , branch = "polkadot-v0.9.31" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, features = [ "disable_allocator" ] , branch = "polkadot-v0.9.36" } [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = [ "std" ] diff --git a/parachain/test-parachains/undying/collator/Cargo.toml b/parachain/test-parachains/undying/collator/Cargo.toml index 638548050768..14d568aa83f5 100644 --- a/parachain/test-parachains/undying/collator/Cargo.toml +++ b/parachain/test-parachains/undying/collator/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "test-parachain-undying-collator" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Collator for the undying test parachain" -edition = "2021" +edition.workspace = true +version.workspace = true +authors.workspace = true [[bin]] name = "undying-collator" @@ -27,9 +27,9 @@ polkadot-service = { path = "../../../../node/service", features = ["rococo-nati polkadot-node-primitives = { path = "../../../../node/primitives" } polkadot-node-subsystem = { path = "../../../../node/subsystem" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } # This one is tricky. Even though it is not used directly by the collator, we still need it for the # `puppet_worker` binary, which is required for the integration test. However, this shouldn't be @@ -40,8 +40,8 @@ polkadot-node-core-pvf = { path = "../../../../node/core/pvf" } polkadot-parachain = { path = "../../.." } polkadot-test-service = { path = "../../../../node/test/service" } -substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-test-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } -tokio = { version = "1.19", features = ["macros"] } +tokio = { version = "1.22.0", features = ["macros"] } diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 6458e18cea2b..71b054470bc0 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -1,33 +1,31 @@ [package] name = "polkadot-primitives" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] -serde = { version = "1.0.137", optional = true, features = ["derive"] } -scale-info = { version = "2.1.2", default-features = false, features = ["bit-vec", "derive"] } -parity-scale-codec = { version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -primitives = { package = "sp-core", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -application-crypto = { package = "sp-application-crypto", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-consensus-slots = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -runtime_primitives = { package = "sp-runtime", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -polkadot-parachain = { path = "../parachain", default-features = false } -polkadot-core-primitives = { path = "../core-primitives", default-features = false } -trie = { package = "sp-trie", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } hex-literal = "0.3.4" -parity-util-mem = { version = "0.12.0", default-features = false, optional = true } +parity-scale-codec = { version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.1.2", default-features = false, features = ["bit-vec", "derive"] } +serde = { version = "1.0.137", optional = true, features = ["derive"] } + +application-crypto = { package = "sp-application-crypto", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +primitives = { package = "sp-core", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +runtime_primitives = { package = "sp-runtime", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-consensus-slots = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.36" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } + +polkadot-core-primitives = { path = "../core-primitives", default-features = false } +polkadot-parachain = { path = "../parachain", default-features = false } [features] default = ["std"] @@ -37,22 +35,18 @@ std = [ "scale-info/std", "primitives/std", "inherents/std", - "trie/std", "sp-api/std", "sp-authority-discovery/std", "sp-consensus-slots/std", "sp-keystore", "sp-std/std", "sp-io/std", - "sp-version/std", "sp-staking/std", "sp-arithmetic/std", "runtime_primitives/std", "serde", - "parity-util-mem", "polkadot-parachain/std", "polkadot-core-primitives/std", "bitvec/std", - "frame-system/std", ] runtime-benchmarks = [] diff --git a/primitives/src/v2/mod.rs b/primitives/src/v2/mod.rs index e31d0e4d36f9..606ffd59920c 100644 --- a/primitives/src/v2/mod.rs +++ b/primitives/src/v2/mod.rs @@ -19,7 +19,12 @@ use bitvec::vec::BitVec; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_std::prelude::*; +use sp_std::{ + marker::PhantomData, + prelude::*, + slice::{Iter, IterMut}, + vec::IntoIter, +}; use application_crypto::KeyTypeId; use inherents::InherentIdentifier; @@ -42,8 +47,6 @@ pub use polkadot_parachain::primitives::{ LOWEST_PUBLIC_ID, LOWEST_USER_ID, }; -#[cfg(feature = "std")] -use parity_util_mem::{MallocSizeOf, MallocSizeOfOps}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -72,16 +75,6 @@ mod collator_app { /// Identity that collators use. pub type CollatorId = collator_app::Public; -#[cfg(feature = "std")] -impl MallocSizeOf for CollatorId { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - 0 - } - fn constant_size() -> Option { - Some(0) - } -} - /// A Parachain collator keypair. #[cfg(feature = "std")] pub type CollatorPair = collator_app::Pair; @@ -89,16 +82,6 @@ pub type CollatorPair = collator_app::Pair; /// Signature on candidate's block data by a collator. pub type CollatorSignature = collator_app::Signature; -#[cfg(feature = "std")] -impl MallocSizeOf for CollatorSignature { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - 0 - } - fn constant_size() -> Option { - Some(0) - } -} - /// The key type ID for a parachain validator key. pub const PARACHAIN_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"para"); @@ -113,19 +96,15 @@ mod validator_app { /// so we define it to be the same type as `SessionKey`. In the future it may have different crypto. pub type ValidatorId = validator_app::Public; -#[cfg(feature = "std")] -impl MallocSizeOf for ValidatorId { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - 0 - } - fn constant_size() -> Option { - Some(0) - } +/// Trait required for type specific indices e.g. `ValidatorIndex` and `GroupIndex` +pub trait TypeIndex { + /// Returns the index associated to this value. + fn type_index(&self) -> usize; } /// Index of the validator is used as a lightweight replacement of the `ValidatorId` when appropriate. #[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))] pub struct ValidatorIndex(pub u32); // We should really get https://github.com/paritytech/polkadot/issues/2403 going .. @@ -135,6 +114,12 @@ impl From for ValidatorIndex { } } +impl TypeIndex for ValidatorIndex { + fn type_index(&self) -> usize { + self.0 as usize + } +} + application_crypto::with_pair! { /// A Parachain validator keypair. pub type ValidatorPair = validator_app::Pair; @@ -146,16 +131,6 @@ application_crypto::with_pair! { /// so we define it to be the same type as `SessionKey`. In the future it may have different crypto. pub type ValidatorSignature = validator_app::Signature; -#[cfg(feature = "std")] -impl MallocSizeOf for ValidatorSignature { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - 0 - } - fn constant_size() -> Option { - Some(0) - } -} - /// A declarations of storage keys where an external observer can find some interesting data. pub mod well_known_keys { use super::{HrmpChannelId, Id}; @@ -389,16 +364,6 @@ application_crypto::with_pair! { pub type AssignmentPair = assignment_app::Pair; } -#[cfg(feature = "std")] -impl MallocSizeOf for AssignmentId { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - 0 - } - fn constant_size() -> Option { - Some(0) - } -} - /// The index of the candidate in the list of candidates fully included as-of the block. pub type CandidateIndex = u32; @@ -448,7 +413,7 @@ fn check_collator_signature>( /// A unique descriptor of the candidate receipt. #[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Hash, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(Hash))] pub struct CandidateDescriptor { /// The ID of the para this is a candidate for. pub para_id: Id, @@ -490,7 +455,6 @@ impl> CandidateDescriptor { /// A candidate-receipt. #[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct CandidateReceipt { /// The descriptor of the candidate. pub descriptor: CandidateDescriptor, @@ -527,7 +491,7 @@ pub struct FullCandidateReceipt { /// A candidate-receipt with commitments directly included. #[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Hash, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(Hash))] pub struct CommittedCandidateReceipt { /// The descriptor of the candidate. pub descriptor: CandidateDescriptor, @@ -608,7 +572,7 @@ impl Ord for CommittedCandidateReceipt { /// The `PersistedValidationData` should be relatively lightweight primarily because it is constructed /// during inclusion for each candidate and therefore lies on the critical path of inclusion. #[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Default, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(Default))] pub struct PersistedValidationData { /// The parent head-data. pub parent_head: HeadData, @@ -629,7 +593,7 @@ impl PersistedValidationData { /// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation. #[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Hash, MallocSizeOf, Default))] +#[cfg_attr(feature = "std", derive(Hash, Default))] pub struct CandidateCommitments { /// Messages destined to be interpreted by the Relay chain itself. pub upward_messages: Vec, @@ -749,7 +713,7 @@ pub fn check_candidate_backing + Clone + Encode>( .zip(backed.validity_votes.iter()) { let validator_id = validator_lookup(val_in_group_idx).ok_or(())?; - let payload = attestation.signed_payload(hash.clone(), signing_context); + let payload = attestation.signed_payload(hash, signing_context); let sig = attestation.signature(); if sig.verify(&payload[..], &validator_id) { @@ -770,7 +734,7 @@ pub fn check_candidate_backing + Clone + Encode>( #[derive( Encode, Decode, Default, PartialOrd, Ord, Eq, PartialEq, Clone, Copy, TypeInfo, RuntimeDebug, )] -#[cfg_attr(feature = "std", derive(Hash, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(Hash))] pub struct CoreIndex(pub u32); impl From for CoreIndex { @@ -779,9 +743,15 @@ impl From for CoreIndex { } } +impl TypeIndex for CoreIndex { + fn type_index(&self) -> usize { + self.0 as usize + } +} + /// The unique (during session) index of a validator group. #[derive(Encode, Decode, Default, Clone, Copy, Debug, PartialEq, Eq, TypeInfo)] -#[cfg_attr(feature = "std", derive(Hash, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(Hash))] pub struct GroupIndex(pub u32); impl From for GroupIndex { @@ -790,6 +760,12 @@ impl From for GroupIndex { } } +impl TypeIndex for GroupIndex { + fn type_index(&self) -> usize { + self.0 as usize + } +} + /// A claim on authoring the next block for a given parathread. #[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] #[cfg_attr(feature = "std", derive(PartialEq))] @@ -817,7 +793,7 @@ pub enum CoreOccupied { /// A helper data-type for tracking validator-group rotations. #[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(PartialEq, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(PartialEq))] pub struct GroupRotationInfo { /// The block number where the session started. pub session_start_block: N, @@ -905,7 +881,7 @@ impl GroupRotationInfo { /// Information about a core which is currently occupied. #[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(PartialEq, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(PartialEq))] pub struct OccupiedCore { // NOTE: this has no ParaId as it can be deduced from the candidate descriptor. /// If this core is freed by availability, this is the assignment that is next up on this @@ -922,7 +898,6 @@ pub struct OccupiedCore { /// A bitfield with 1 bit for each validator in the set. `1` bits mean that the corresponding /// validators has attested to availability on-chain. A 2/3+ majority of `1` bits means that /// this will be available. - #[cfg_attr(feature = "std", ignore_malloc_size_of = "outside type")] pub availability: BitVec, /// The group assigned to distribute availability pieces of this candidate. pub group_responsible: GroupIndex, @@ -941,7 +916,7 @@ impl OccupiedCore { /// Information about a core which is currently occupied. #[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(PartialEq, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(PartialEq))] pub struct ScheduledCore { /// The ID of a para scheduled. pub para_id: Id, @@ -951,7 +926,7 @@ pub struct ScheduledCore { /// The state of a particular availability core. #[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(PartialEq, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(PartialEq))] pub enum CoreState { /// The core is currently occupied. #[codec(index = 0)] @@ -1002,7 +977,7 @@ pub enum OccupiedCoreAssumption { /// An even concerning a candidate. #[derive(Clone, Encode, Decode, TypeInfo, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(PartialEq, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(PartialEq))] pub enum CandidateEvent { /// This candidate receipt was backed in the most recent block. /// This includes the core index the candidate is now occupying. @@ -1021,7 +996,7 @@ pub enum CandidateEvent { /// Scraped runtime backing votes and resolved disputes. #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(PartialEq, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(PartialEq))] pub struct ScrapedOnChainVotes { /// The session in which the block was included. pub session: SessionIndex, @@ -1210,7 +1185,6 @@ impl From for runtime_primitives::DigestItem { /// /// Statements are either in favor of the candidate's validity or against it. #[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub enum DisputeStatement { /// A valid statement, of the given kind. #[codec(index = 0)] @@ -1291,7 +1265,6 @@ impl DisputeStatement { /// Different kinds of statements of validity on a candidate. #[derive(Encode, Decode, Copy, Clone, PartialEq, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub enum ValidDisputeStatementKind { /// An explicit statement issued as part of a dispute. #[codec(index = 0)] @@ -1309,7 +1282,6 @@ pub enum ValidDisputeStatementKind { /// Different kinds of statements of invalidity on a candidate. #[derive(Encode, Decode, Copy, Clone, PartialEq, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub enum InvalidDisputeStatementKind { /// An explicit statement issued as part of a dispute. #[codec(index = 0)] @@ -1338,7 +1310,6 @@ impl ExplicitDisputeStatement { /// A set of statements about a specific candidate. #[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub struct DisputeStatementSet { /// The candidate referenced by this set. pub candidate_hash: CandidateHash, @@ -1403,22 +1374,6 @@ pub struct DisputeState { pub concluded_at: Option, } -#[cfg(feature = "std")] -impl MallocSizeOf for DisputeState { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - // destructuring to make sure no new fields are added to the struct without modifying this function - let Self { validators_for, validators_against, start, concluded_at } = self; - - // According to the documentation `.capacity()` might not return a byte aligned value, so just in case: - let align_eight = |d: usize| (d + 7) / 8; - - align_eight(validators_for.capacity()) + - align_eight(validators_against.capacity()) + - start.size_of(ops) + - concluded_at.size_of(ops) - } -} - /// Parachains inherent-data passed into the runtime by a block author #[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] pub struct InherentData { @@ -1435,7 +1390,6 @@ pub struct InherentData { /// An either implicit or explicit attestation to the validity of a parachain /// candidate. #[derive(Clone, Eq, PartialEq, Decode, Encode, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(MallocSizeOf))] pub enum ValidityAttestation { /// Implicit validity attestation by issuing. /// This corresponds to issuance of a `Candidate` statement. @@ -1569,6 +1523,72 @@ impl CompactStatement { } } +/// `IndexedVec` struct indexed by type specific indices. +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(PartialEq))] +pub struct IndexedVec(Vec, PhantomData K>); + +impl Default for IndexedVec { + fn default() -> Self { + Self(vec![], PhantomData) + } +} + +impl From> for IndexedVec { + fn from(validators: Vec) -> Self { + Self(validators, PhantomData) + } +} + +impl FromIterator for IndexedVec { + fn from_iter>(iter: T) -> Self { + Self(Vec::from_iter(iter), PhantomData) + } +} + +impl IndexedVec +where + V: Clone, +{ + /// Returns a reference to an element indexed using `K`. + pub fn get(&self, index: K) -> Option<&V> + where + K: TypeIndex, + { + self.0.get(index.type_index()) + } + + /// Returns number of elements in vector. + pub fn len(&self) -> usize { + self.0.len() + } + + /// Returns contained vector. + pub fn to_vec(&self) -> Vec { + self.0.clone() + } + + /// Returns an iterator over the underlying vector. + pub fn iter(&self) -> Iter<'_, V> { + self.0.iter() + } + + /// Returns a mutable iterator over the underlying vector. + pub fn iter_mut(&mut self) -> IterMut<'_, V> { + self.0.iter_mut() + } + + /// Creates a consuming iterator. + pub fn into_iter(self) -> IntoIter { + self.0.into_iter() + } + + /// Returns true if the underlying container is empty. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + /// The maximum number of validators `f` which may safely be faulty. /// /// The total number of validators is `n = 3f + e` where `e in { 1, 2, 3 }`. @@ -1584,7 +1604,7 @@ pub fn supermajority_threshold(n: usize) -> usize { /// Information about validator sets of a session. #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(PartialEq, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(PartialEq))] pub struct SessionInfo { /****** New in v2 *******/ /// All the validators actively participating in parachain consensus. @@ -1603,14 +1623,13 @@ pub struct SessionInfo { /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148). /// /// `SessionInfo::validators` will be limited to to `max_validators` when set. - pub validators: Vec, + pub validators: IndexedVec, /// Validators' authority discovery keys for the session in canonical ordering. /// /// NOTE: The first `validators.len()` entries will match the corresponding validators in /// `validators`, afterwards any remaining authorities can be found. This is any authorities not /// participating in parachain consensus - see /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148) - #[cfg_attr(feature = "std", ignore_malloc_size_of = "outside type")] pub discovery_keys: Vec, /// The assignment keys for validators. /// @@ -1626,7 +1645,7 @@ pub struct SessionInfo { /// Validators in shuffled ordering - these are the validator groups as produced /// by the `Scheduler` module for the session and are typically referred to by /// `GroupIndex`. - pub validator_groups: Vec>, + pub validator_groups: IndexedVec>, /// The number of availability cores used by the protocol during this session. pub n_cores: u32, /// The zeroth delay tranche width. @@ -1670,7 +1689,7 @@ impl PvfCheckStatement { /// Old, v1-style info about session info. Only needed for limited /// backwards-compatibility. #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(PartialEq, MallocSizeOf))] +#[cfg_attr(feature = "std", derive(PartialEq))] pub struct OldV1SessionInfo { /// Validators in canonical ordering. /// @@ -1679,14 +1698,13 @@ pub struct OldV1SessionInfo { /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148). /// /// `SessionInfo::validators` will be limited to to `max_validators` when set. - pub validators: Vec, + pub validators: IndexedVec, /// Validators' authority discovery keys for the session in canonical ordering. /// /// NOTE: The first `validators.len()` entries will match the corresponding validators in /// `validators`, afterwards any remaining authorities can be found. This is any authorities not /// participating in parachain consensus - see /// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148) - #[cfg_attr(feature = "std", ignore_malloc_size_of = "outside type")] pub discovery_keys: Vec, /// The assignment keys for validators. /// @@ -1702,7 +1720,7 @@ pub struct OldV1SessionInfo { /// Validators in shuffled ordering - these are the validator groups as produced /// by the `Scheduler` module for the session and are typically referred to by /// `GroupIndex`. - pub validator_groups: Vec>, + pub validator_groups: IndexedVec>, /// The number of availability cores used by the protocol during this session. pub n_cores: u32, /// The zeroth delay tranche width. diff --git a/primitives/test-helpers/Cargo.toml b/primitives/test-helpers/Cargo.toml index a07b66f41ab6..054cf6f67685 100644 --- a/primitives/test-helpers/Cargo.toml +++ b/primitives/test-helpers/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "polkadot-primitives-test-helpers" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-application-crypto = { package = "sp-application-crypto", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.31" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-application-crypto = { package = "sp-application-crypto", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", features = ["std"] , branch = "polkadot-v0.9.36" } polkadot-primitives = { path = "../" } rand = "0.8.5" diff --git a/roadmap/implementers-guide/README.md b/roadmap/implementers-guide/README.md index 70a10a26a765..996041f176bb 100644 --- a/roadmap/implementers-guide/README.md +++ b/roadmap/implementers-guide/README.md @@ -1,9 +1,17 @@ # The Polkadot Parachain Host Implementers' Guide The implementers' guide is compiled from several source files with [`mdBook`](https://github.com/rust-lang/mdBook). -To view it live, locally, from the repo root: + +## Hosted build + +This is available [here](https://paritytech.github.io/polkadot/book/). + +## Local build + +To view it locally from the repo root: Ensure graphviz is installed: + ```sh brew install graphviz # for macOS sudo apt-get install graphviz # for Ubuntu/Debian @@ -12,7 +20,16 @@ sudo apt-get install graphviz # for Ubuntu/Debian Then install and build the book: ```sh -cargo install mdbook mdbook-linkcheck mdbook-graphviz +cargo install mdbook mdbook-linkcheck mdbook-graphviz mdbook-mermaid mdbook-last-changed mdbook serve roadmap/implementers-guide +``` + +and in a second terminal window run: + +```sh open http://localhost:3000 ``` + +## Specification + +See also the Polkadot specification [hosted](https://spec.polkadot.network/), and its [source](https://github.com/w3f/polkadot-spec). diff --git a/roadmap/implementers-guide/book.toml b/roadmap/implementers-guide/book.toml index 8805ca4c38c3..0ced0e26f9a0 100644 --- a/roadmap/implementers-guide/book.toml +++ b/roadmap/implementers-guide/book.toml @@ -9,8 +9,14 @@ title = "The Polkadot Parachain Host Implementers' Guide" command = "mdbook-graphviz" [preprocessor.mermaid] command = "mdbook-mermaid" +[preprocessor.last-changed] +command = "mdbook-last-changed" +renderer = ["html"] [output.html] +additional-css = ["last-changed.css"] additional-js = ["mermaid.min.js", "mermaid-init.js"] +# Repository URL used in the last-changed link. +git-repository-url = "https://github.com/paritytech/polkadot" [output.linkcheck] diff --git a/roadmap/implementers-guide/last-changed.css b/roadmap/implementers-guide/last-changed.css new file mode 100644 index 000000000000..744dc6efc7ec --- /dev/null +++ b/roadmap/implementers-guide/last-changed.css @@ -0,0 +1,7 @@ +footer { + font-size: 0.8em; + text-align: center; + margin-top: 50px; + border-top: 1px solid black; + padding: 5px 0; +} diff --git a/roadmap/implementers-guide/src/SUMMARY.md b/roadmap/implementers-guide/src/SUMMARY.md index bcf87aad8a49..c504b9ac1923 100644 --- a/roadmap/implementers-guide/src/SUMMARY.md +++ b/roadmap/implementers-guide/src/SUMMARY.md @@ -75,7 +75,6 @@ - [Availability](types/availability.md) - [Overseer and Subsystem Protocol](types/overseer-protocol.md) - [Runtime](types/runtime.md) - - [Chain](types/chain.md) - [Messages](types/messages.md) - [Network](types/network.md) - [Approvals](types/approval.md) diff --git a/roadmap/implementers-guide/src/glossary.md b/roadmap/implementers-guide/src/glossary.md index a64c5bd00a50..d379c2813b59 100644 --- a/roadmap/implementers-guide/src/glossary.md +++ b/roadmap/implementers-guide/src/glossary.md @@ -2,43 +2,47 @@ Here you can find definitions of a bunch of jargon, usually specific to the Polkadot project. -- BABE: (Blind Assignment for Blockchain Extension). The algorithm validators use to safely extend the Relay Chain. See [the Polkadot wiki][0] for more information. -- Backable Candidate: A Parachain Candidate which is backed by a majority of validators assigned to a given parachain. -- Backed Candidate: A Backable Candidate noted in a relay-chain block -- Backing: A set of statements proving that a Parachain Candidate is backable. -- Collator: A node who generates Proofs-of-Validity (PoV) for blocks of a specific parachain. -- DMP: (Downward Message Passing). Message passing from the relay-chain to a parachain. Also there is a runtime parachains module with the same name. -- DMQ: (Downward Message Queue). A message queue for messages from the relay-chain down to a parachain. A parachain has +- **Approval Checker:** A validator who randomly self-selects so to perform validity checks on a parablock which is pending approval. +- **BABE:** (Blind Assignment for Blockchain Extension). The algorithm validators use to safely extend the Relay Chain. See [the Polkadot wiki][0] for more information. +- **Backable Candidate:** A Parachain Candidate which is backed by a majority of validators assigned to a given parachain. +- **Backed Candidate:** A Backable Candidate noted in a relay-chain block +- **Backing:** A set of statements proving that a Parachain Candidate is backable. +- **Collator:** A node who generates Proofs-of-Validity (PoV) for blocks of a specific parachain. +- **DMP:** (Downward Message Passing). Message passing from the relay-chain to a parachain. Also there is a runtime parachains module with the same name. +- **DMQ:** (Downward Message Queue). A message queue for messages from the relay-chain down to a parachain. A parachain has exactly one downward message queue. -- Extrinsic: An element of a relay-chain block which triggers a specific entry-point of a runtime module with given arguments. -- GRANDPA: (Ghost-based Recursive ANcestor Deriving Prefix Agreement). The algorithm validators use to guarantee finality of the Relay Chain. -- HRMP: (Horizontally Relay-routed Message Passing). A mechanism for message passing between parachains (hence horizontal) that leverages the relay-chain storage. Predates XCMP. Also there is a runtime parachains module with the same name. -- Inclusion Pipeline: The set of steps taken to carry a Parachain Candidate from authoring, to backing, to availability and full inclusion in an active fork of its parachain. -- Module: A component of the Runtime logic, encapsulating storage, routines, and entry-points. -- Module Entry Point: A recipient of new information presented to the Runtime. This may trigger routines. -- Module Routine: A piece of code executed within a module by block initialization, closing, or upon an entry point being triggered. This may execute computation, and read or write storage. -- MQC: (Message Queue Chain). A cryptographic data structure that resembles an append-only linked list which doesn't store original values but only their hashes. The whole structure is described by a single hash, referred as a "head". When a value is appended, it's contents hashed with the previous head creating a hash that becomes a new head. -- Node: A participant in the Polkadot network, who follows the protocols of communication and connection to other nodes. Nodes form a peer-to-peer network topology without a central authority. -- Parachain Candidate, or Candidate: A proposed block for inclusion into a parachain. -- Parablock: A block in a parachain. -- Parachain: A constituent chain secured by the Relay Chain's validators. -- Parachain Validators: A subset of validators assigned during a period of time to back candidates for a specific parachain -- Parathread: A parachain which is scheduled on a pay-as-you-go basis. -- PDK (Parachain Development Kit): A toolset that allows one to develop a parachain. Cumulus is a PDK. -- Preimage: In our context, if `H(X) = Y` where `H` is a hash function and `Y` is the hash, then `X` is the hash preimage. -- Proof-of-Validity (PoV): A stateless-client proof that a parachain candidate is valid, with respect to some validation function. -- Relay Parent: A block in the relay chain, referred to in a context where work is being done in the context of the state at this block. -- Router: The router module is a meta module that consists of three runtime modules responsible for routing messages between paras and the relay chain. The three separate runtime modules are: Dmp, Ump, Hrmp, each responsible for the respective part of message routing. -- Runtime: The relay-chain state machine. -- Runtime Module: See Module. -- Runtime API: A means for the node-side behavior to access structured information based on the state of a fork of the blockchain. -- Secondary Checker: A validator who has been randomly selected to perform secondary approval checks on a parablock which is pending approval. -- Subsystem: A long-running task which is responsible for carrying out a particular category of work. -- UMP: (Upward Message Passing) A vertical message passing mechanism from a parachain to the relay chain. -- Validator: Specially-selected node in the network who is responsible for validating parachain blocks and issuing attestations about their validity. -- Validation Function: A piece of Wasm code that describes the state-transition function of a parachain. -- VMP: (Vertical Message Passing) A family of mechanisms that are responsible for message exchange between the relay chain and parachains. -- XCMP (Cross-Chain Message Passing) A type of horizontal message passing (i.e. between parachains) that allows secure message passing directly between parachains and has minimal resource requirements from the relay chain, thus highly scalable. +- **Extrinsic:** An element of a relay-chain block which triggers a specific entry-point of a runtime module with given arguments. +- **GRANDPA:** (Ghost-based Recursive ANcestor Deriving Prefix Agreement). The algorithm validators use to guarantee finality of the Relay Chain. +- **HRMP:** (Horizontally Relay-routed Message Passing). A mechanism for message passing between parachains (hence horizontal) that leverages the relay-chain storage. Predates XCMP. Also there is a runtime parachains module with the same name. +- **Inclusion Pipeline:** The set of steps taken to carry a Parachain Candidate from authoring, to backing, to availability and full inclusion in an active fork of its parachain. +- **Module:** A component of the Runtime logic, encapsulating storage, routines, and entry-points. +- **Module Entry Point:** A recipient of new information presented to the Runtime. This may trigger routines. +- **Module Routine:** A piece of code executed within a module by block initialization, closing, or upon an entry point being triggered. This may execute computation, and read or write storage. +- **MQC:** (Message Queue Chain). A cryptographic data structure that resembles an append-only linked list which doesn't store original values but only their hashes. The whole structure is described by a single hash, referred as a "head". When a value is appended, it's contents hashed with the previous head creating a hash that becomes a new head. +- **Node:** A participant in the Polkadot network, who follows the protocols of communication and connection to other nodes. Nodes form a peer-to-peer network topology without a central authority. +- **Parachain Candidate, or Candidate:** A proposed block for inclusion into a parachain. +- **Parablock:** A block in a parachain. +- **Parachain:** A constituent chain secured by the Relay Chain's validators. +- **Parachain Validators:** A subset of validators assigned during a period of time to back candidates for a specific parachain +- **Parathread:** A parachain which is scheduled on a pay-as-you-go basis. +- **PDK (Parachain Development Kit):** A toolset that allows one to develop a parachain. Cumulus is a PDK. +- **Preimage:** In our context, if `H(X) = Y` where `H` is a hash function and `Y` is the hash, then `X` is the hash preimage. +- **Proof-of-Validity (PoV):** A stateless-client proof that a parachain candidate is valid, with respect to some validation function. +- **PVF:** Parachain Validation Function. The validation code that is run by validators on parachains or parathreads. +- **PVF Prechecking:** This is the process of initially checking the PVF when it is first added. We attempt preparation of the PVF and make sure it succeeds within a given timeout. +- **PVF Preparation:** This is the process of preparing the WASM blob and includes both prevalidation and compilation. As prevalidation is pretty minimal right now, preparation mostly consists of compilation. +- **Relay Parent:** A block in the relay chain, referred to in a context where work is being done in the context of the state at this block. +- **Runtime:** The relay-chain state machine. +- **Runtime Module:** See Module. +- **Runtime API:** A means for the node-side behavior to access structured information based on the state of a fork of the blockchain. +- **Subsystem:** A long-running task which is responsible for carrying out a particular category of work. +- **UMP:** (Upward Message Passing) A vertical message passing mechanism from a parachain to the relay chain. +- **Validator:** Specially-selected node in the network who is responsible for validating parachain blocks and issuing attestations about their validity. +- **Validation Function:** A piece of Wasm code that describes the state-transition function of a parachain. +- **VMP:** (Vertical Message Passing) A family of mechanisms that are responsible for message exchange between the relay chain and parachains. +- **XCMP:** (Cross-Chain Message Passing) A type of horizontal message passing (i.e. between parachains) that allows secure message passing directly between parachains and has minimal resource requirements from the relay chain, thus highly scalable. + +## See Also Also of use is the [Substrate Glossary](https://substrate.dev/docs/en/knowledgebase/getting-started/glossary). diff --git a/roadmap/implementers-guide/src/node/availability/README.md b/roadmap/implementers-guide/src/node/availability/README.md index 46ee4b204982..76bd6467e178 100644 --- a/roadmap/implementers-guide/src/node/availability/README.md +++ b/roadmap/implementers-guide/src/node/availability/README.md @@ -1,3 +1,3 @@ # Availability Subsystems -The availability subsystems are responsible for ensuring that Proofs of Validity of backed candidates are widely available within the validator set, without requiring every node to retain a full copy. They accomplish this by broadly distributing erasure-coded chunks of the PoV, keeping track of which validator has which chunk by means of signed bitfields. They are also responsible for reassembling a complete PoV when required, e.g. when a fisherman reports a potentially invalid block. +The availability subsystems are responsible for ensuring that Proofs of Validity of backed candidates are widely available within the validator set, without requiring every node to retain a full copy. They accomplish this by broadly distributing erasure-coded chunks of the PoV, keeping track of which validator has which chunk by means of signed bitfields. They are also responsible for reassembling a complete PoV when required, e.g. when an approval checker needs to validate a parachain block. diff --git a/roadmap/implementers-guide/src/node/disputes/README.md b/roadmap/implementers-guide/src/node/disputes/README.md index 7b28b908fbbe..2db891aa216f 100644 --- a/roadmap/implementers-guide/src/node/disputes/README.md +++ b/roadmap/implementers-guide/src/node/disputes/README.md @@ -5,7 +5,7 @@ This section is for the node-side subsystems that lead to participation in dispu * Participation. Participate in active disputes. When a node becomes aware of a dispute, it should recover the data for the disputed block, check the validity of the parablock, and issue a statement regarding the validity of the parablock. * Distribution. Validators should notify each other of active disputes and relevant statements over the network. * Submission. When authoring a block, a validator should inspect the state of the parent block and provide any information about disputes that the chain needs as part of the `ParaInherent`. This should initialize new disputes on-chain as necessary. - * Fork-choice and Finality. When observing a block issuing a `DisputeRollback` digest in the header, that branch of the relay chain should be abandoned all the way back to the indicated block. When voting on chains in GRANDPA, no chains that contain blocks that are or have been disputed should be voted on. + * Fork-choice and Finality. When observing a block issuing a `DisputeRollback` digest in the header, that branch of the relay chain should be abandoned all the way back to the indicated block. When voting on chains in GRANDPA, no chains that contain blocks with active disputes or disputes that concluded invalid should be voted on. ## Components diff --git a/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md b/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md index 29a3c5ffa082..260f5843d0e2 100644 --- a/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md +++ b/roadmap/implementers-guide/src/node/disputes/dispute-coordinator.md @@ -9,12 +9,14 @@ In particular the dispute-coordinator is responsible for: - Ensuring that the node is able to raise a dispute in case an invalid candidate is found during approval checking. -- Ensuring malicious approval votes will be recorded, so nodes can get slashed - properly. +- Ensuring approval votes will be recorded. - Coordinating actual participation in a dispute, ensuring that the node participates in any justified dispute in a way that ensures resolution of disputes on the network even in the case of many disputes raised (flood/DoS scenario). +- Ensuring disputes resolve, even for candidates on abandoned forks as much as + reasonably possible, to rule out "free tries" and thus guarantee our gambler's + ruin property. - Provide an API for chain selection, so we can prevent finalization of any chain which has included candidates for which a dispute is either ongoing or concluded invalid and avoid building on chains with an included invalid @@ -22,6 +24,8 @@ In particular the dispute-coordinator is responsible for: - Provide an API for retrieving (resolved) disputes, including all votes, both implicit (approval, backing) and explicit dispute votes. So validators can get rewarded/slashed accordingly. +- Ensure backing votes are recorded and will never get overridden by explicit + votes. ## Ensuring That Disputes Can Be Raised @@ -76,29 +80,38 @@ inefficient process. (Quadratic complexity adds up, with 35 votes in total per c Approval votes are very relevant nonetheless as we are going to see in the next section. -## Ensuring Malicious Approval Votes Will Be Recorded +## Ensuring approval votes will be recorded ### Ensuring Recording +Only votes recorded by the dispute coordinator will be considered for slashing. + While there is no need to record approval votes in the dispute coordinator -preemptively, we do need to make sure they are recorded when a dispute -actually happens. This is because only votes recorded by the dispute -coordinator will be considered for slashing. While the backing group always gets -slashed, a serious attack attempt will likely also consist of malicious approval -checkers which will cast approval votes, although the candidate is invalid. If -we did not import those votes, those nodes would likely cast an `invalid` explicit -vote as part of the dispute in addition to their approval vote and thus avoid a -slash. With the 2/3rd honest assumption it seems unrealistic that malicious -actors will keep sending approval votes once they became aware of a raised -dispute. Hence the most crucial approval votes to import are the early ones -(tranche 0), to take into account network latencies and such we still want to -import approval votes at a later point in time as well (in particular we need to -make sure the dispute can conclude, but more on that later). - -As mentioned already previously, importing votes is most efficient when batched. -At the same time approval voting and disputes are running concurrently so -approval votes are expected to trickle in still, when a dispute is already -ongoing. +preemptively, we make some effort to have any in approval-voting received +approval votes recorded when a dispute actually happens: + +This is not required for concluding the dispute, as nodes send their own vote +anyway (either explicit valid or their existing approval-vote). What nodes can +do though, is participating in approval-voting, casting a vote, but later when a +dispute is raised reconsider their vote and send an explicit invalid vote. If +they managed to only have that one 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 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 all - they could just always +vote "valid" totally risk free. (While they would alwasy risk a slash by voting +invalid.) + + +So we do want to fetch approval votes from approval-voting. Importing votes is +most efficient when batched. At the same time approval voting and disputes are +running concurrently so approval votes are expected to trickle in still, when a +dispute is already ongoing. Hence, we have the following requirements for importing approval votes: @@ -109,12 +122,12 @@ Hence, we have the following requirements for importing approval votes: already running. With a design where approval voting sends votes to the dispute-coordinator by -itself, we would need to make approval voting aware of ongoing disputes and -once it is aware it could start sending all already existing votes batched and +itself, we would need to make approval voting aware of ongoing disputes and once +it is aware it could start sending all already existing votes batched and trickling in votes as they come. The problem with this is, that it adds some unnecessary complexity to approval-voting and also we might still import most of -the votes unbatched, but one-by-one, depending on what point in time the dispute -was raised. +the votes unbatched one-by-one, depending on what point in time the dispute was +raised. Instead of the dispute coordinator informing approval-voting of an ongoing dispute for it to begin forwarding votes to the dispute coordinator, it makes @@ -123,14 +136,11 @@ candidates in dispute. This way, the dispute coordinator can also pick the best time for maximizing the number of votes in the batch. Now the question remains, when should the dispute coordinator ask -approval-voting for votes? As argued above already, querying approval votes at -the beginning of the dispute, will likely already take care of most malicious -votes. Still we would like to have a record of all, if possible. So what are -other points in time we might query approval votes? +approval-voting for votes? In fact for slashing it is only relevant to have them once the dispute concluded, so we can query approval voting the moment the dispute concludes! -There are two potential caveats with this though: +Two concerns that come to mind, are easily addressed: 1. Timing: We would like to rely as little as possible on implementation details of approval voting. In particular, if the dispute is ongoing for a long time, @@ -139,7 +149,7 @@ There are two potential caveats with this though: dispute concludes in all cases? The answer is nuanced, but in general we cannot rely on it. The problem is first, that finalization and approval-voting is an off-chain process so there is no global consensus: As - soon as at least f+1 honest (f= n/3, where n is the number of + soon as at least f+1 honest (f=n/3, where n is the number of validators/nodes) nodes have seen the dispute conclude, finalization will take place and approval votes will be cleared. This would still be fine, if we had some guarantees that those honest nodes will be able to include those @@ -150,31 +160,12 @@ There are two potential caveats with this though: chain can no longer be finalized (some other/better fork already has been). This second problem can somehow be mitigated by also importing votes as soon as a dispute is detected, but not fully resolved. It is still inherently - racy. The problem can be solved in at least two ways: Either go back to full - eager import of approval votes into the dispute-coordinator in some more - efficient manner or by changing requirements on approval-voting, making it - hold on votes longer than necessary for approval-voting itself. Conceptually - both solutions are equivalent, as we make sure votes are available even - without an ongoing dispute. For now, in the interest of time we punt on this - issue: If nodes import votes as soon as a dispute is raised in addition to - when it concludes, we have a good chance of getting relevant votes and even - if not, the fundamental security properties will still hold: Backers are - getting slashed, therefore gambler's ruin is maintained. We would still like - to fix this at [some - point](https://github.com/paritytech/polkadot/issues/5864). -2. There could be a chicken and egg problem: If we wait for approval vote import - for the dispute to conclude, we would run into a problem if we needed those - approval votes to get enough votes to conclude the dispute. Luckily it turns - out that this is not quite true or at least can be made not true easily: As - already mentioned, approval voting and disputes are running concurrently, but - not only that, they race with each other! A node might simultaneously start - participating in a dispute via the dispute coordinator, due to learning about - a dispute via dispute-distribution, while also participating in approval - voting. By distributing our own approval vote we make sure the dispute can - conclude regardless how the race ended (we either participate explicitly - anyway or we sent our already present approval vote). By importing all - approval votes we make it possible to slash malicious approval voters, even - if they also cast an invalid explicit vote. + racy. The good thing is, this should be good enough: We are worried about + lazy approval checkers, the system does not need to be perfect. It should be + enough if there is some risk of getting caught. +2. We are not worried about the dispute not concluding, as nodes will always + send their own vote, regardless of it being an explict or an already existing + approval-vote. Conclusion: As long as we make sure, if our own approval vote gets imported (which would prevent dispute participation) to also distribute it via @@ -183,34 +174,34 @@ approval-voting deleting votes we will import approval votes twice during a dispute: Once when it is raised, to make as sure as possible to see approval votes also for abandoned forks and second when the dispute concludes, to maximize the amount of potentially malicious approval votes to be recorded. The -raciness obviously is not fully resolved by this, [a -ticket](https://github.com/paritytech/polkadot/issues/5864) exists. +raciness obviously is not fully resolved by this, but this is fine as argued +above. Ensuring vote import on chain is covered in the next section. -As already touched: Honest nodes -will likely validate twice, once in approval voting and once via -dispute-participation. Avoiding that does not really seem worthwhile though, as -disputes are for one exceptional, so a little wasted effort won't affect -everyday performance - second, even with eager importing of approval votes, -those doubled work is still present as disputes and approvals are racing. Every -time participation is faster than approval, a node would do double work. +What we don't care about is that honest approval-voters will likely validate +twice, once in approval voting and once via dispute-participation. Avoiding that +does not really seem worthwhile though, as disputes are for one exceptional, so +a little wasted effort won't affect everyday performance - second, even with +eager importing of approval votes, those doubled work is still present as +disputes and approvals are racing. Every time participation is faster than +approval, a node would do double work. ### Ensuring Chain Import While in the previous section we discussed means for nodes to ensure relevant -votes are recorded so attackers get slashed properly, it is crucial to also -discuss the actual chain import. Only if we guarantee that recorded votes will -also get imported on chain (on all potential chains really) we will succeed in -executing slashes. Again approval votes prove to be our weak spot here, but also -backing votes might get missed. +votes are recorded so lazy approval checkers get slashed properly, it is crucial +to also discuss the actual chain import. Only if we guarantee that recorded votes +will get imported on chain (on all potential chains really) we will succeed +in executing slashes. Particularly we need to make sure backing votes end up on +chain consistently. Dispute distribution will make sure all explicit dispute votes get distributed among nodes which includes current block producers (current authority set) which is an important property: If the dispute carries on across an era change, we need to ensure that the new validator set will learn about any disputes and their votes, so they can put that information on chain. Dispute-distribution -luckily has this property and sends votes to the current authority set always. +luckily has this property and always sends votes to the current authority set. The issue is, for dispute-distribution, nodes send only their own explicit (or in some cases their approval vote) in addition to some opposing vote. This guarantees that at least some backing or approval vote will be present at the @@ -223,13 +214,13 @@ production in the current set - they might only exist on an already abandoned fork. This means a block producer that just joined the set, might not have seen any of them. -For approvals it is even more tricky: Approval voting together with finalization -is a completely off-chain process therefore those protocols don't care about -block production at all. Approval votes only have a guarantee of being -propagated between the nodes that are responsible for finalizing the concerned -blocks. This implies that on an era change the current authority set, will not -necessarily get informed about any approval votes for the previous era. Hence -even if all validators of the previous era successfully recorded all approval +For approvals it is even more tricky and less necessary: Approval voting together +with finalization is a completely off-chain process therefore those protocols +don't care about block production at all. Approval votes only have a guarantee of +being propagated between the nodes that are responsible for finalizing the +concerned blocks. This implies that on an era change the current authority set, +will not necessarily get informed about any approval votes for the previous era. +Hence even if all validators of the previous era successfully recorded all approval votes in the dispute coordinator, they won't get a chance to put them on chain, hence they won't be considered for slashing. @@ -305,7 +296,7 @@ to send out a thousand tiny network messages by just sending out a single garbage message, is still a significant amplification and is nothing to ignore - this could absolutely be used to cause harm! -#### Participation +### Participation As explained, just blindly participating in any "dispute" that comes along is not a good idea. First we would like to make sure the dispute is actually @@ -323,13 +314,16 @@ participation at all on any _vote import_ if any of the following holds true: - We have seen the disputed candidate backed in some not yet finalized block on at least one fork of the chain. This ensures the candidate is at least not completely made up and there has been some effort already flown into that - candidate. + candidate. Generally speaking a dispute shouldn't be raised for a candidate + which is backed but is not yet included. Disputes are raised during approval + checking. We participate on such disputes as a precaution - maybe we haven't + seen the `CandidateIncluded` event yet? - The dispute is already confirmed: Meaning that 1/3+1 nodes already participated, as this suggests in our threat model that there was at least one honest node that already voted, so the dispute must be genuine. Note: A node might be out of sync with the chain and we might only learn about a -block including a candidate, after we learned about the dispute. This means, we +block, including a candidate, after we learned about the dispute. This means, we have to re-evaluate participation decisions on block import! With this, nodes won't waste significant resources on completely made up @@ -341,7 +335,7 @@ obviously only need to worry about order if participations start queuing up. We treat participation for candidates that we have seen included with priority and put them on a priority queue which sorts participation based on the block -number of the relay parent of that candidate and for candidates with the same +number of the relay parent of the candidate and for candidates with the same relay parent height further by the `CandidateHash`. This ordering is globally unique and also prioritizes older candidates. @@ -352,27 +346,57 @@ times instead of just once to the oldest offender. This is obviously a good idea, in particular it makes it impossible for an attacker to prevent rolling back a very old candidate, by keeping raising disputes for newer candidates. -For candidates we have not seen included, but we have our availability piece -available we put participation on a best-effort queue, which at the moment is -processed on the basis how often we requested participation locally, which -equals the number of times we imported votes for that dispute. The idea is, if -we have not seen the candidate included, but the dispute is valid, other nodes -will have seen it included - so the more votes there are, the more likely it is -a valid dispute and we should implicitly arrive at a similar ordering as the -nodes that are able to sort based on the relay parent block height. +For candidates we have not seen included, but we know are backed (thanks to +chain scraping) or we have seen a dispute with 1/3+1 participation (confirmed +dispute) on them - we put participation on a best-effort queue. It has got the +same ordering as the priority one - by block heights of the relay parent, older +blocks are with priority. There is a possibility not to be able to obtain the +block number of the parent when we are inserting the dispute in the queue. To +account for races, we will promote any existing participation request to the +priority queue once we learn about an including block. NOTE: this is still work +in progress and is tracked by [this +issue](https://github.com/paritytech/polkadot/issues/5875). + +### Abandoned Forks + +Finalization: As mentioned we care about included and backed candidates on any +non-finalized chain, given that any disputed chain will not get finalized, we +don't need to care about finalized blocks, but what about forks that fall behind +the finalized chain in terms of block number? For those we would still like to +be able to participate in any raised disputes, otherwise attackers might be able +to avoid a slash if they manage to create a better fork after they learned about +the approval checkers. Therefore we do care about those forks even after they +have fallen behind the finalized chain. + +For simplicity we also care about the actual finalized chain (not just forks) up +to a certain depth. We do have to limit the depth, because otherwise we open a +DoS vector again. The depth (into the finalized chain) should be oriented on the +approval-voting execution timeout, in particular it should be significantly +larger. Otherwise by the time the execution is allowed to finish, we already +dropped information about those candidates and the dispute could not conclude. + +## Import -#### Import +### Spam Considerations -In the last section we looked at how to treat queuing participations to handle -heavy dispute load well. This already ensures, that honest nodes won't amplify -cheap DoS attacks. There is one minor issue remaining: Even if we delay +In the last section we looked at how to treat queuing participations to +handle heavy dispute load well. This already ensures, that honest nodes won't +amplify cheap DoS attacks. There is one minor issue remaining: Even if we delay participation until we have some confirmation of the authenticity of the -dispute, we should also not blindly import all votes arriving into the -database as this might be used to just slowly fill up disk space, until the node -is no longer functional. This leads to our last protection mechanism at the -dispute coordinator level (dispute-distribution also has its own), which is spam -slots. For each import, where we don't know whether it might be spam or not we -increment a counter for each signing participant of explicit `invalid` votes. +dispute, we should also not blindly import all votes arriving into the database +as this might be used to just slowly fill up disk space, until the node is no +longer functional. This leads to our last protection mechanism at the dispute +coordinator level (dispute-distribution also has its own), which is spam slots. +For each import containing an invalid vote, where we don't know whether it might +be spam or not we increment a counter for each signing participant of explicit +`invalid` votes. + +What votes do we treat as a potential spam? A vote will increase a spam slot if +and only if all of the following conditions are satisfied: + +* the candidate under dispute was not seen included nor backed on any chain +* the dispute is not confirmed +* we haven't cast a vote for the dispute The reason this works is because we only need to worry about actual dispute votes. Import of backing votes are already rate limited and concern only real @@ -383,6 +407,17 @@ an explicit `invalid` vote in the import. Only a third of the validators can be malicious, so spam disk usage is limited to `2*vote_size*n/3*NUM_SPAM_SLOTS`, with `n` being the number of validators. +### Backing Votes + +Backing votes are in some way special. For starters they are the only valid +votes that are guaranteed to exist for any valid dispute to be raised. Second +they are the only votes that commit to a shorter execution timeout +`BACKING_EXECUTION_TIMEOUT`, compared to a more lenient timeout used in approval +voting. To account properly for execution time variance across machines, +slashing might treat backing votes differently (more aggressively) than other +voting `valid` votes. Hence in import we shall never override a backing vote +with another valid vote. They can not be assumed to be interchangeable. + ## Attacks & Considerations The following attacks on the priority queue and best-effort queues are diff --git a/roadmap/implementers-guide/src/node/utility/candidate-validation.md b/roadmap/implementers-guide/src/node/utility/candidate-validation.md index 5393368c5c6b..6e7a5f3d0c8f 100644 --- a/roadmap/implementers-guide/src/node/utility/candidate-validation.md +++ b/roadmap/implementers-guide/src/node/utility/candidate-validation.md @@ -48,4 +48,47 @@ Once we have all parameters, we can spin up a background task to perform the val If we can assume the presence of the relay-chain state (that is, during processing [`CandidateValidationMessage`][CVM]`::ValidateFromChainState`) we can run all the checks that the relay-chain would run at the inclusion time thus confirming that the candidate will be accepted. +### PVF Host + +The PVF host is responsible for handling requests to prepare and execute PVF +code blobs. + +One high-level goal is to make PVF operations as deterministic as possible, to +reduce the rate of disputes. Disputes can happen due to e.g. a job timing out on +one machine, but not another. While we do not yet have full determinism, there +are some dispute reduction mechanisms in place right now. + +#### Retrying execution requests + +If the execution request fails during **preparation**, we will retry if it is +possible that the preparation error was transient (e.g. if the error was a panic +or time out). We will only retry preparation if another request comes in after +15 minutes, to ensure any potential transient conditions had time to be +resolved. We will retry up to 5 times. + +If the actual **execution** of the artifact fails, we will retry once if it was +an ambiguous error after a brief delay, to allow any potential transient +conditions to clear. + +#### Preparation timeouts + +We use timeouts for both preparation and execution jobs to limit the amount of +time they can take. As the time for a job can vary depending on the machine and +load on the machine, this can potentially lead to disputes where some validators +successfuly execute a PVF and others don't. + +One dispute mitigation we have in place is a more lenient timeout for +preparation during execution than during pre-checking. The rationale is that the +PVF has already passed pre-checking, so we know it should be valid, and we allow +it to take longer than expected, as this is likely due to an issue with the +machine and not the PVF. + +#### CPU clock timeouts + +Another timeout-related mitigation we employ is to measure the time taken by +jobs using CPU time, rather than wall clock time. This is because the CPU time +of a process is less variable under different system conditions. When the +overall system is under heavy load, the wall clock time of a job is affected +more than the CPU time. + [CVM]: ../../types/overseer-protocol.md#validationrequesttype diff --git a/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md b/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md index b0f58346da99..fd75ce9e3804 100644 --- a/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md +++ b/roadmap/implementers-guide/src/node/utility/pvf-prechecker.md @@ -12,11 +12,11 @@ This subsytem does not produce any output messages either. The subsystem will, h If the node is running in a collator mode, this subsystem will be disabled. The PVF pre-checker subsystem keeps track of the PVFs that are relevant for the subsystem. -To be relevant for the subsystem, a PVF must be returned by `pvfs_require_precheck` [`pvfs_require_precheck` runtime API][PVF pre-checking runtime API] in any of the active leaves. If the PVF is not present in any of the active leaves, it ceases to be relevant. +To be relevant for the subsystem, a PVF must be returned by the [`pvfs_require_precheck` runtime API][PVF pre-checking runtime API] in any of the active leaves. If the PVF is not present in any of the active leaves, it ceases to be relevant. When a PVF just becomes relevant, the subsystem will send a message to the [Candidate Validation] subsystem asking for the pre-check. -Upon receving a message from the candidate-validation subsystem, the pre-checker will note down that the PVF has its judgement and will also sign and submit a [`PvfCheckStatement`] via the [`submit_pvf_check_statement` runtime API][PVF pre-checking runtime API]. In case, a judgement was received for a PVF that is no longer in view it is ignored. It is possible that the candidate validation was not able to check the PVF. In that case, the PVF pre-checker will abstain and won't submit any check statements. +Upon receving a message from the candidate-validation subsystem, the pre-checker will note down that the PVF has its judgement and will also sign and submit a [`PvfCheckStatement`][PvfCheckStatement] via the [`submit_pvf_check_statement` runtime API][PVF pre-checking runtime API]. In case, a judgement was received for a PVF that is no longer in view it is ignored. It is possible that the candidate validation was not able to check the PVF. In that case, the PVF pre-checker will abstain and won't submit any check statements. Since a vote only is valid during [one session][overview], the subsystem will have to resign and submit the statements for for the new session. The new session is assumed to be started if at least one of the leaves has a greater session index that was previously observed in any of the leaves. @@ -28,4 +28,4 @@ If the node is not in the active validator set, it will still perform all the ch [Runtime API]: runtime-api.md [PVF pre-checking runtime API]: ../../runtime-api/pvf-prechecking.md [Candidate Validation]: candidate-validation.md -[`PvfCheckStatement`]: ../../types/pvf-prechecking.md +[PvfCheckStatement]: ../../types/pvf-prechecking.md#pvfcheckstatement diff --git a/roadmap/implementers-guide/src/protocol-overview.md b/roadmap/implementers-guide/src/protocol-overview.md index 77b3a7448c44..fa5a866e6121 100644 --- a/roadmap/implementers-guide/src/protocol-overview.md +++ b/roadmap/implementers-guide/src/protocol-overview.md @@ -8,7 +8,6 @@ First, it's important to go over the main actors we have involved in this protoc 1. Validators. These nodes are responsible for validating proposed parachain blocks. They do so by checking a Proof-of-Validity (PoV) of the block and ensuring that the PoV remains available. They put financial capital down as "skin in the game" which can be slashed (destroyed) if they are proven to have misvalidated. 1. Collators. These nodes are responsible for creating the Proofs-of-Validity that validators know how to check. Creating a PoV typically requires familiarity with the transaction format and block authoring rules of the parachain, as well as having access to the full state of the parachain. -1. Fishermen. These are user-operated, permissionless nodes whose goal is to catch misbehaving validators in exchange for a bounty. Collators and validators can behave as Fishermen too. Fishermen aren't necessary for security, and aren't covered in-depth by this document. This implies a simple pipeline where collators send validators parachain blocks and their requisite PoV to check. Then, validators validate the block using the PoV, signing statements which describe either the positive or negative outcome, and with enough positive statements, the block can be noted on the relay-chain. Negative statements are not a veto but will lead to a dispute, with those on the wrong side being slashed. If another validator later detects that a validator or group of validators incorrectly signed a statement claiming a block was valid, then those validators will be _slashed_, with the checker receiving a bounty. diff --git a/roadmap/implementers-guide/src/pvf-prechecking.md b/roadmap/implementers-guide/src/pvf-prechecking.md index 1dc7611c0cef..4dce61d2a83b 100644 --- a/roadmap/implementers-guide/src/pvf-prechecking.md +++ b/roadmap/implementers-guide/src/pvf-prechecking.md @@ -1,32 +1,12 @@ # PVF Pre-checking Overview -> ⚠️ This discusses a mechanism that is currently under-development. Follow the progress under [#3211]. - -## Terms - -This functionality involves several processes which may be potentially -confusing: - -- **Prechecking:** This is the process of initially checking the PVF when it is - first added. We attempt *preparation* of the PVF and make sure it succeeds - within a given timeout. -- **Execution:** This actually executes the PVF. The node may not have the - artifact from prechecking, in which case this process also includes a - *preparation* job. The timeout for preparation here is more lenient than when - prechecking. -- **Preparation:** This is the process of preparing the WASM blob and includes - both *prevalidation* and *compilation*. As prevalidation is pretty minimal - right now, preparation mostly consists of compilation. Note that *prechecking* - just consists of preparation, whereas *execution* will also prepare the PVF if - the artifact is not already found. -- **Prevalidation:** Right now this just tries to deserialize the binary with - parity-wasm. It is a part of *preparation*. -- **Compilation:** This is the process of compiling a PVF from wasm code to - machine code. It is a part of *preparation*. +> ⚠️ This discusses a mechanism that is currently under-development. Follow the progress under [#3211][3211]. ## Motivation -Parachains' and parathreads' validation function is described by a wasm module that we refer to as a PVF. Since it's a wasm module the typical way of executing it is to compile it to machine code. Typically an optimizing compiler consists of algorithms that are able to optimize the resulting machine code heavily. However, while those algorithms perform quite well for a typical wasm code produced by standard toolchains (e.g. rustc/LLVM), those algorithms can be abused to consume a lot of resources. Moreover, since those algorithms are rather complex there is a lot of room for a bug that can crash the compiler. +Parachains' and parathreads' validation function is described by a wasm module that we refer to as a PVF. Since a PVF is a wasm module the typical way of executing it is to compile it to machine code. + +Typically an optimizing compiler consists of algorithms that are able to optimize the resulting machine code heavily. However, while those algorithms perform quite well for a typical wasm code produced by standard toolchains (e.g. rustc/LLVM), those algorithms can be abused to consume a lot of resources. Moreover, since those algorithms are rather complex there is a lot of room for a bug that can crash the compiler. If compilation of a Parachain Validation Function (PVF) takes too long or uses too much memory, this can leave a node in limbo as to whether a candidate of that parachain is valid or not. @@ -66,7 +46,19 @@ The logic described above is implemented by the [paras] module. On the node-side, there is a PVF pre-checking [subsystem][pvf-prechecker-subsystem] that scans the chain for new PVFs via using [runtime APIs][pvf-runtime-api]. Upon finding a new PVF, the subsystem will initiate a PVF pre-checking request and wait for the result. Whenever the result is obtained, the subsystem will use the [runtime API][pvf-runtime-api] to submit a vote for the PVF. The vote is an unsigned transaction. The vote will be distributed via the gossip similarly to a normal transaction. Eventually a block producer will include the vote into the block where it will be handled by the [runtime][paras]. -[#3211]: https://github.com/paritytech/polkadot/issues/3211 +## Pre-checking Summary + +Parachains' and parathreads' validation function is described by a wasm module that we refer to as a PVF. + +In order to make the PVF usable for candidate validation it has to be registered on-chain. + +As part of the registration process, it has to go through pre-checking. Pre-checking is a game of attempting preparation and reporting the results back on-chain. + +We define preparation as a process that: validates the consistency of the wasm binary (aka prevalidation) and the compilation of the wasm module into machine code (refered to as artifact). + +Besides pre-checking, preparation can also be triggered by execution, since a compiled artifact is needed for the execution. If an artifact already exists, execution will skip preparation. If it does do preparation, execution uses a more lenient timeout than preparation, to avoid the situation where honest validators fail on valid, pre-checked PVFs. + +[3211]: https://github.com/paritytech/polkadot/issues/3211 [paras]: runtime/paras.md [pvf-runtime-api]: runtime-api/pvf-prechecking.md [pvf-prechecker-subsystem]: node/utility/pvf-prechecker.md diff --git a/roadmap/implementers-guide/src/runtime/README.md b/roadmap/implementers-guide/src/runtime/README.md index 178346e184f5..f1f9d6c950e2 100644 --- a/roadmap/implementers-guide/src/runtime/README.md +++ b/roadmap/implementers-guide/src/runtime/README.md @@ -14,16 +14,18 @@ There is some functionality of the relay chain relating to parachains that we al We will split the logic of the runtime up into these modules: -* Initializer: manage initialization order of the other modules. +* Initializer: manages initialization order of the other modules. * Shared: manages shared storage and configurations for other modules. -* Configuration: manage configuration and configuration updates in a non-racy manner. -* Paras: manage chain-head and validation code for parachains and parathreads. +* Configuration: manages configuration and configuration updates in a non-racy manner. +* Paras: manages chain-head and validation code for parachains and parathreads. * Scheduler: manages parachain and parathread scheduling as well as validator assignments. * Inclusion: handles the inclusion and availability of scheduled parachains and parathreads. -* Validity: handles secondary checks and dispute resolution for included, available parablocks. +* SessionInfo: manages various session keys of validators and other params stored per session. +* Disputes: handles dispute resolution for included, available parablocks. +* Slashing: handles slashing logic for concluded disputes. * HRMP: handles horizontal messages between paras. -* UMP: Handles upward messages from a para to the relay chain. -* DMP: Handles downward messages from the relay chain to the para. +* UMP: handles upward messages from a para to the relay chain. +* DMP: handles downward messages from the relay chain to the para. The [Initializer module](initializer.md) is special - it's responsible for handling the initialization logic of the other modules to ensure that the correct initialization order and related invariants are maintained. The other modules won't specify a on-initialize logic, but will instead expose a special semi-private routine that the initialization module will call. The other modules are relatively straightforward and perform the roles described above. diff --git a/roadmap/implementers-guide/src/types/approval.md b/roadmap/implementers-guide/src/types/approval.md index e85a625b0710..b58e0a8187e1 100644 --- a/roadmap/implementers-guide/src/types/approval.md +++ b/roadmap/implementers-guide/src/types/approval.md @@ -6,7 +6,7 @@ The public key of a keypair used by a validator for determining assignments to a ## `AssignmentCert` -An `AssignmentCert`, short for Assignment Certificate, is a piece of data provided by a validator to prove that they have been selected to perform secondary approval checks on an included candidate. +An `AssignmentCert`, short for Assignment Certificate, is a piece of data provided by a validator to prove that they have been selected to perform approval checks on an included candidate. These certificates can be checked in the context of a specific block, candidate, and validator assignment VRF key. The block state will also provide further context about the availability core states at that block. diff --git a/roadmap/implementers-guide/src/types/candidate.md b/roadmap/implementers-guide/src/types/candidate.md index b9d5900b7f17..729c72180ee5 100644 --- a/roadmap/implementers-guide/src/types/candidate.md +++ b/roadmap/implementers-guide/src/types/candidate.md @@ -76,7 +76,7 @@ struct CandidateDescriptor { collator: CollatorId, /// The blake2-256 hash of the persisted validation data. These are extra parameters /// derived from relay-chain state that influence the validity of the block which - /// must also be kept available for secondary checkers. + /// must also be kept available for approval checkers. persisted_validation_data_hash: Hash, /// The blake2-256 hash of the `pov-block`. pov_hash: Hash, @@ -92,6 +92,22 @@ struct CandidateDescriptor { } ``` +## `ValidationParams` + +```rust +/// Validation parameters for evaluating the parachain validity function. +pub struct ValidationParams { + /// Previous head-data. + pub parent_head: HeadData, + /// The collation body. + pub block_data: BlockData, + /// The current relay-chain block number. + pub relay_parent_number: RelayChainBlockNumber, + /// The relay-chain block's storage root. + pub relay_parent_storage_root: Hash, +} +``` + ## `PersistedValidationData` The validation data provides information about how to create the inputs for validation of a candidate. This information is derived from the chain state and will vary from para to para, although some of the fields may be the same for every para. @@ -100,7 +116,7 @@ Since this data is used to form inputs to the validation function, it needs to b Furthermore, the validation data acts as a way to authorize the additional data the collator needs to pass to the validation function. For example, the validation function can check whether the incoming messages (e.g. downward messages) were actually sent by using the data provided in the validation data using so called MQC heads. -Since the commitments of the validation function are checked by the relay-chain, secondary checkers can rely on the invariant that the relay-chain only includes para-blocks for which these checks have already been done. As such, there is no need for the validation data used to inform validators and collators about the checks the relay-chain will perform to be persisted by the availability system. +Since the commitments of the validation function are checked by the relay-chain, approval checkers can rely on the invariant that the relay-chain only includes para-blocks for which these checks have already been done. As such, there is no need for the validation data used to inform validators and collators about the checks the relay-chain will perform to be persisted by the availability system. The `PersistedValidationData` should be relatively lightweight primarily because it is constructed during inclusion for each candidate and therefore lies on the critical path of inclusion. diff --git a/roadmap/implementers-guide/src/types/chain.md b/roadmap/implementers-guide/src/types/chain.md deleted file mode 100644 index e8ec6cea8f4a..000000000000 --- a/roadmap/implementers-guide/src/types/chain.md +++ /dev/null @@ -1,30 +0,0 @@ -# Chain - -Types pertaining to the relay-chain - events, structures, etc. - -## Block Import Event - -```rust -/// Indicates that a new block has been added to the blockchain. -struct BlockImportEvent { - /// The block header-hash. - hash: Hash, - /// The header itself. - header: Header, - /// Whether this block is considered the head of the best chain according to the - /// event emitter's fork-choice rule. - new_best: bool, -} -``` - -## Block Finalization Event - -```rust -/// Indicates that a new block has been finalized. -struct BlockFinalizationEvent { - /// The block header-hash. - hash: Hash, - /// The header of the finalized block. - header: Header, -} -``` diff --git a/roadmap/implementers-guide/src/types/overseer-protocol.md b/roadmap/implementers-guide/src/types/overseer-protocol.md index 4b9dc97c27e2..41d624670363 100644 --- a/roadmap/implementers-guide/src/types/overseer-protocol.md +++ b/roadmap/implementers-guide/src/types/overseer-protocol.md @@ -681,9 +681,7 @@ enum ProvisionerMessage { The Runtime API subsystem is responsible for providing an interface to the state of the chain's runtime. -This is fueled by an auxiliary type encapsulating all request types defined in the Runtime API section of the guide. - -> To do: link to the Runtime API section. Not possible currently because of https://github.com/Michael-F-Bryan/mdbook-linkcheck/issues/25. Once v0.7.1 is released it will work. +This is fueled by an auxiliary type encapsulating all request types defined in the [Runtime API section](../runtime-api) of the guide. ```rust enum RuntimeApiRequest { @@ -827,7 +825,7 @@ pub enum CandidateValidationMessage { /// /// This request doesn't involve acceptance criteria checking, therefore only useful for the /// cases where the validity of the candidate is established. This is the case for the typical - /// use-case: secondary checkers would use this request relying on the full prior checks + /// use-case: approval checkers would use this request relying on the full prior checks /// performed by the relay-chain. ValidateFromExhaustive( PersistedValidationData, diff --git a/roadmap/implementers-guide/src/types/pvf-prechecking.md b/roadmap/implementers-guide/src/types/pvf-prechecking.md index 331429bd1fc5..f68f1e60feee 100644 --- a/roadmap/implementers-guide/src/types/pvf-prechecking.md +++ b/roadmap/implementers-guide/src/types/pvf-prechecking.md @@ -1,5 +1,7 @@ # PVF Pre-checking types +## `PvfCheckStatement` + > ⚠️ This type was added in v2. One of the main units of information on which PVF pre-checking voting is build is the `PvfCheckStatement`. diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index a1201553db24..db20edcd8716 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -1,32 +1,32 @@ [package] name = "polkadot-rpc" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] -jsonrpsee = { version = "0.15.1", features = ["server"] } +jsonrpsee = { version = "0.16.2", features = ["server"] } polkadot-primitives = { path = "../primitives" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-consensus-babe-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-consensus-epochs = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-sync-state-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -txpool-api = { package = "sc-transaction-pool-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-rpc-system = { package = "substrate-frame-rpc-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -substrate-state-trie-migration-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-consensus-babe-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-consensus-epochs = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-sync-state-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +txpool-api = { package = "sc-transaction-pool-api", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-rpc-system = { package = "substrate-frame-rpc-system", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +substrate-state-trie-migration-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 2b3497832caa..43efefcae15b 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -108,11 +108,7 @@ where + Sync + 'static, C::Api: frame_rpc_system::AccountNonceApi, - C::Api: pallet_mmr_rpc::MmrRuntimeApi< - Block, - ::Hash, - BlockNumber, - >, + C::Api: mmr_rpc::MmrRuntimeApi::Hash, BlockNumber>, C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, C::Api: BabeApi, C::Api: BlockBuilder, @@ -123,7 +119,7 @@ where { use beefy_gadget_rpc::{Beefy, BeefyApiServer}; use frame_rpc_system::{System, SystemApiServer}; - use pallet_mmr_rpc::{Mmr, MmrApiServer}; + use mmr_rpc::{Mmr, MmrApiServer}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; use sc_consensus_babe_rpc::{Babe, BabeApiServer}; use sc_finality_grandpa_rpc::{Grandpa, GrandpaApiServer}; diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 4284317aa5d9..c922fead1b95 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-runtime-common" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] impl-trait-for-tuples = "0.2.2" @@ -15,34 +15,35 @@ serde = { version = "1.0.137", default-features = false } serde_derive = { version = "1.0.117", optional = true } static_assertions = "1.1.0" -beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-npos-elections = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, package = "sp-beefy" , branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-npos-elections = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-bags-list = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking-reward-fn = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-bags-list = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false } libsecp256k1 = { version = "0.7.0", default-features = false } @@ -53,10 +54,10 @@ xcm = { path = "../../xcm", default-features = false } [dev-dependencies] hex-literal = "0.3.4" -frame-support-test = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +frame-support-test = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } serde_json = "1.0.81" libsecp256k1 = "0.7.0" test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../primitives/test-helpers" } @@ -84,6 +85,7 @@ std = [ "pallet-beefy-mmr/std", "pallet-session/std", "pallet-staking/std", + "pallet-staking-reward-fn/std", "pallet-timestamp/std", "pallet-vesting/std", "pallet-transaction-payment/std", diff --git a/runtime/common/slot_range_helper/Cargo.toml b/runtime/common/slot_range_helper/Cargo.toml index 25baa5a0e65a..77ad48851e19 100644 --- a/runtime/common/slot_range_helper/Cargo.toml +++ b/runtime/common/slot_range_helper/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "slot-range-helper" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] paste = "1.0" enumn = "0.1.5" parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } -sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/runtime/common/src/claims.rs b/runtime/common/src/claims.rs index bb0663ec34f7..1bb5b0cdc8d3 100644 --- a/runtime/common/src/claims.rs +++ b/runtime/common/src/claims.rs @@ -247,12 +247,9 @@ pub mod pallet { impl GenesisBuild for GenesisConfig { fn build(&self) { // build `Claims` - self.claims - .iter() - .map(|(a, b, _, _)| (a.clone(), b.clone())) - .for_each(|(a, b)| { - Claims::::insert(a, b); - }); + self.claims.iter().map(|(a, b, _, _)| (*a, *b)).for_each(|(a, b)| { + Claims::::insert(a, b); + }); // build `Total` Total::::put( self.claims @@ -266,17 +263,16 @@ pub mod pallet { // build `Signing` self.claims .iter() - .filter_map(|(a, _, _, s)| Some((a.clone(), s.clone()?))) + .filter_map(|(a, _, _, s)| Some((*a, (*s)?))) .for_each(|(a, s)| { Signing::::insert(a, s); }); // build `Preclaims` - self.claims - .iter() - .filter_map(|(a, _, i, _)| Some((i.clone()?, a.clone()))) - .for_each(|(i, a)| { + self.claims.iter().filter_map(|(a, _, i, _)| Some((i.clone()?, *a))).for_each( + |(i, a)| { Preclaims::::insert(i, a); - }); + }, + ); } } @@ -538,7 +534,7 @@ impl Pallet { } let mut v = b"\x19Ethereum Signed Message:\n".to_vec(); v.extend(rev.into_iter().rev()); - v.extend_from_slice(&prefix[..]); + v.extend_from_slice(prefix); v.extend_from_slice(what); v.extend_from_slice(extra); v @@ -645,7 +641,7 @@ where info: &DispatchInfoOf, len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + self.validate(who, call, info, len).map(|_| ()) } // diff --git a/runtime/common/src/crowdloan/migration.rs b/runtime/common/src/crowdloan/migration.rs index 775d70f92458..468c2a572b51 100644 --- a/runtime/common/src/crowdloan/migration.rs +++ b/runtime/common/src/crowdloan/migration.rs @@ -15,7 +15,53 @@ // along with Polkadot. If not, see . use super::*; -use frame_support::{storage_alias, Twox64Concat}; +use frame_support::{ + dispatch::GetStorageVersion, + storage_alias, + traits::{OnRuntimeUpgrade, StorageVersion}, + Twox64Concat, +}; + +pub struct MigrateToTrackInactive(sp_std::marker::PhantomData); +impl OnRuntimeUpgrade for MigrateToTrackInactive { + fn on_runtime_upgrade() -> Weight { + let onchain_version = Pallet::::on_chain_storage_version(); + + if onchain_version == 0 { + let mut translated = 0u64; + for index in Funds::::iter_keys() { + let b = CurrencyOf::::total_balance(&Pallet::::fund_account_id(index.into())); + CurrencyOf::::deactivate(b); + translated.saturating_inc(); + } + + StorageVersion::new(1).put::>(); + log::info!(target: "runtime::crowdloan", "Summed {} funds, storage to version 1", translated); + T::DbWeight::get().reads_writes(translated * 2 + 1, translated * 2 + 1) + } else { + log::info!(target: "runtime::crowdloan", "Migration did not execute. This probably should be removed"); + T::DbWeight::get().reads(1) + } + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + let total = Funds::::iter_keys() + .map(|index| { + CurrencyOf::::total_balance(&Pallet::::fund_account_id(index.into())) + }) + .fold(BalanceOf::::zero(), |a, i| a.saturating_add(i)); + Ok((total, CurrencyOf::::active_issuance()).encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(total: Vec) -> Result<(), &'static str> { + let (total, active) = <(BalanceOf, BalanceOf)>::decode(&mut total.as_slice()) + .expect("the state parameter should be something that was generated by pre_upgrade"); + assert_eq!(active - total, CurrencyOf::::active_issuance(), "the total be correct"); + Ok(()) + } +} /// Migrations for using fund index to create fund accounts instead of para ID. pub mod crowdloan_index_migration { @@ -67,12 +113,10 @@ pub mod crowdloan_index_migration { let leases = Leases::::get(para_id).unwrap_or_default(); let mut found_lease_deposit = false; - for maybe_deposit in leases.iter() { - if let Some((who, _amount)) = maybe_deposit { - if *who == old_fund_account { - found_lease_deposit = true; - break - } + for (who, _amount) in leases.iter().flatten() { + if *who == old_fund_account { + found_lease_deposit = true; + break } } if found_lease_deposit { @@ -112,11 +156,9 @@ pub mod crowdloan_index_migration { weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 2)); let mut leases = Leases::::get(para_id).unwrap_or_default(); - for maybe_deposit in leases.iter_mut() { - if let Some((who, _amount)) = maybe_deposit { - if *who == old_fund_account { - *who = new_fund_account.clone(); - } + for (who, _amount) in leases.iter_mut().flatten() { + if *who == old_fund_account { + *who = new_fund_account.clone(); } } @@ -162,13 +204,11 @@ pub mod crowdloan_index_migration { let leases = Leases::::get(para_id).unwrap_or_default(); let mut new_account_found = false; - for maybe_deposit in leases.iter() { - if let Some((who, _amount)) = maybe_deposit { - if *who == old_fund_account { - panic!("Old fund account found after migration!"); - } else if *who == new_fund_account { - new_account_found = true; - } + for (who, _amount) in leases.iter().flatten() { + if *who == old_fund_account { + panic!("Old fund account found after migration!"); + } else if *who == new_fund_account { + new_account_found = true; } } if new_account_found { diff --git a/runtime/common/src/crowdloan/mod.rs b/runtime/common/src/crowdloan/mod.rs index 1f84af3f2ee9..224f06c0d6e4 100644 --- a/runtime/common/src/crowdloan/mod.rs +++ b/runtime/common/src/crowdloan/mod.rs @@ -51,6 +51,8 @@ pub mod migration; +// TODO: Expose the total amount held. + use crate::{ slot_range::SlotRange, traits::{Auctioneer, Registrar}, @@ -182,9 +184,13 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; + /// The current storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] #[pallet::without_storage_info] + #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(_); #[pallet::config] @@ -488,6 +494,7 @@ pub mod pallet { ensure!(balance > Zero::zero(), Error::::NoContributions); CurrencyOf::::transfer(&fund_account, &who, balance, AllowDeath)?; + CurrencyOf::::reactivate(balance); Self::contribution_kill(fund.fund_index, &who); fund.raised = fund.raised.saturating_sub(balance); @@ -527,6 +534,7 @@ pub mod pallet { break } CurrencyOf::::transfer(&fund_account, &who, balance, AllowDeath)?; + CurrencyOf::::reactivate(balance); Self::contribution_kill(fund.fund_index, &who); fund.raised = fund.raised.saturating_sub(balance); refund_count += 1; @@ -777,6 +785,7 @@ impl Pallet { } CurrencyOf::::transfer(&who, &fund_account, value, existence)?; + CurrencyOf::::deactivate(value); let balance = old_balance.saturating_add(value); Self::contribution_put(fund.fund_index, &who, &balance, &memo); diff --git a/runtime/common/src/impls.rs b/runtime/common/src/impls.rs index 939b753092f5..51dbdd80c781 100644 --- a/runtime/common/src/impls.rs +++ b/runtime/common/src/impls.rs @@ -18,6 +18,8 @@ use crate::NegativeImbalance; use frame_support::traits::{Currency, Imbalance, OnUnbalanced}; +use primitives::v2::Balance; +use sp_runtime::Perquintill; /// Logic for the author to get a portion of fees. pub struct ToAuthor(sp_std::marker::PhantomData); @@ -57,6 +59,45 @@ where } } +pub fn era_payout( + total_staked: Balance, + total_stakable: Balance, + max_annual_inflation: Perquintill, + period_fraction: Perquintill, + auctioned_slots: u64, +) -> (Balance, Balance) { + use pallet_staking_reward_fn::compute_inflation; + use sp_runtime::traits::Saturating; + + let min_annual_inflation = Perquintill::from_rational(25u64, 1000u64); + let delta_annual_inflation = max_annual_inflation.saturating_sub(min_annual_inflation); + + // 30% reserved for up to 60 slots. + let auction_proportion = Perquintill::from_rational(auctioned_slots.min(60), 200u64); + + // Therefore the ideal amount at stake (as a percentage of total issuance) is 75% less the + // amount that we expect to be taken up with auctions. + let ideal_stake = Perquintill::from_percent(75).saturating_sub(auction_proportion); + + let stake = Perquintill::from_rational(total_staked, total_stakable); + let falloff = Perquintill::from_percent(5); + let adjustment = compute_inflation(stake, ideal_stake, falloff); + let staking_inflation = + min_annual_inflation.saturating_add(delta_annual_inflation * adjustment); + + let max_payout = period_fraction * max_annual_inflation * total_stakable; + let staking_payout = (period_fraction * staking_inflation) * total_stakable; + let rest = max_payout.saturating_sub(staking_payout); + + let other_issuance = total_stakable.saturating_sub(total_staked); + if total_staked > other_issuance { + let _cap_rest = Perquintill::from_rational(other_issuance, total_staked) * staking_payout; + // We don't do anything with this, but if we wanted to, we could introduce a cap on the + // treasury amount with: `rest = rest.min(cap_rest);` + } + (staking_payout, rest) +} + #[cfg(test)] mod tests { use super::*; @@ -209,4 +250,44 @@ mod tests { assert_eq!(Balances::free_balance(Treasury::account_id()), 8); }); } + + #[test] + fn compute_inflation_should_give_sensible_results() { + assert_eq!( + pallet_staking_reward_fn::compute_inflation( + Perquintill::from_percent(75), + Perquintill::from_percent(75), + Perquintill::from_percent(5), + ), + Perquintill::one() + ); + assert_eq!( + pallet_staking_reward_fn::compute_inflation( + Perquintill::from_percent(50), + Perquintill::from_percent(75), + Perquintill::from_percent(5), + ), + Perquintill::from_rational(2u64, 3u64) + ); + assert_eq!( + pallet_staking_reward_fn::compute_inflation( + Perquintill::from_percent(80), + Perquintill::from_percent(75), + Perquintill::from_percent(5), + ), + Perquintill::from_rational(1u64, 2u64) + ); + } + + #[test] + fn era_payout_should_give_sensible_results() { + assert_eq!( + era_payout(75, 100, Perquintill::from_percent(10), Perquintill::one(), 0,), + (10, 0) + ); + assert_eq!( + era_payout(80, 100, Perquintill::from_percent(10), Perquintill::one(), 0,), + (6, 4) + ); + } } diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index ac5fc69a28e4..3fb1d9021307 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -40,7 +40,7 @@ mod mock; use frame_support::{ parameter_types, traits::{ConstU32, Currency, OneSessionHandler}, - weights::{constants::WEIGHT_PER_SECOND, Weight}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, }; use frame_system::limits; use primitives::v2::{AssignmentId, Balance, BlockNumber, ValidatorId, MAX_POV_SIZE}; @@ -71,7 +71,7 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(1); pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// The storage proof size is not limited so far. pub const MAXIMUM_BLOCK_WEIGHT: Weight = - WEIGHT_PER_SECOND.saturating_mul(2).set_proof_size(MAX_POV_SIZE as u64); + Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), MAX_POV_SIZE as u64); const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct()); diff --git a/runtime/common/src/paras_registrar.rs b/runtime/common/src/paras_registrar.rs index 7245cd92d304..bfcc91e3ba71 100644 --- a/runtime/common/src/paras_registrar.rs +++ b/runtime/common/src/paras_registrar.rs @@ -35,6 +35,7 @@ use sp_std::{prelude::*, result}; use crate::traits::{OnSwap, Registrar}; pub use pallet::*; use parity_scale_codec::{Decode, Encode}; +use runtime_parachains::paras::ParaKind; use scale_info::TypeInfo; use sp_runtime::{ traits::{CheckedSub, Saturating}, @@ -570,7 +571,7 @@ impl Pallet { }; ensure!(paras::Pallet::::lifecycle(id).is_none(), Error::::AlreadyRegistered); let (genesis, deposit) = - Self::validate_onboarding_data(genesis_head, validation_code, false)?; + Self::validate_onboarding_data(genesis_head, validation_code, ParaKind::Parathread)?; let deposit = deposit_override.unwrap_or(deposit); if let Some(additional) = deposit.checked_sub(&deposited) { @@ -613,7 +614,7 @@ impl Pallet { fn validate_onboarding_data( genesis_head: HeadData, validation_code: ValidationCode, - parachain: bool, + para_kind: ParaKind, ) -> Result<(ParaGenesisArgs, BalanceOf), sp_runtime::DispatchError> { let config = configuration::Pallet::::config(); ensure!(validation_code.0.len() > 0, Error::::EmptyCode); @@ -628,7 +629,7 @@ impl Pallet { .saturating_add(per_byte_fee.saturating_mul((genesis_head.0.len() as u32).into())) .saturating_add(per_byte_fee.saturating_mul((validation_code.0.len() as u32).into())); - Ok((ParaGenesisArgs { genesis_head, validation_code, parachain }, deposit)) + Ok((ParaGenesisArgs { genesis_head, validation_code, para_kind }, deposit)) } /// Swap a parachain and parathread, which involves scheduling an appropriate lifecycle update. diff --git a/runtime/common/src/slots/migration.rs b/runtime/common/src/slots/migration.rs index 33d221b209d5..a87f1cd7a074 100644 --- a/runtime/common/src/slots/migration.rs +++ b/runtime/common/src/slots/migration.rs @@ -31,18 +31,16 @@ pub mod slots_crowdloan_index_migration { for (para_id, leases) in Leases::::iter() { let old_fund_account = old_fund_account_id::(para_id); - for maybe_deposit in leases.iter() { - if let Some((who, _amount)) = maybe_deposit { - if *who == old_fund_account { - let crowdloan = - crowdloan::Funds::::get(para_id).ok_or("no crowdloan found")?; - log::info!( - target: "runtime", - "para_id={:?}, old_fund_account={:?}, fund_id={:?}, leases={:?}", - para_id, old_fund_account, crowdloan.fund_index, leases, - ); - break - } + for (who, _amount) in leases.iter().flatten() { + if *who == old_fund_account { + let crowdloan = + crowdloan::Funds::::get(para_id).ok_or("no crowdloan found")?; + log::info!( + target: "runtime", + "para_id={:?}, old_fund_account={:?}, fund_id={:?}, leases={:?}", + para_id, old_fund_account, crowdloan.fund_index, leases, + ); + break } } } @@ -61,11 +59,9 @@ pub mod slots_crowdloan_index_migration { let new_fund_account = crowdloan::Pallet::::fund_account_id(fund.fund_index); // look for places the old account is used, and replace with the new account. - for maybe_deposit in leases.iter_mut() { - if let Some((who, _amount)) = maybe_deposit { - if *who == old_fund_account { - *who = new_fund_account.clone(); - } + for (who, _amount) in leases.iter_mut().flatten() { + if *who == old_fund_account { + *who = new_fund_account.clone(); } } @@ -83,11 +79,9 @@ pub mod slots_crowdloan_index_migration { let old_fund_account = old_fund_account_id::(para_id); log::info!(target: "runtime", "checking para_id: {:?}", para_id); // check the old fund account doesn't exist anywhere. - for maybe_deposit in leases.iter() { - if let Some((who, _amount)) = maybe_deposit { - if *who == old_fund_account { - panic!("old fund account found after migration!"); - } + for (who, _amount) in leases.iter().flatten() { + if *who == old_fund_account { + panic!("old fund account found after migration!"); } } } diff --git a/runtime/common/src/slots/mod.rs b/runtime/common/src/slots/mod.rs index 673d9f86e1bd..21391dc3d774 100644 --- a/runtime/common/src/slots/mod.rs +++ b/runtime/common/src/slots/mod.rs @@ -1039,8 +1039,8 @@ mod benchmarking { // Worst case scenario, T parathreads onboard, and C parachains offboard. manage_lease_period_start { // Assume reasonable maximum of 100 paras at any time - let c in 1 .. 100; - let t in 1 .. 100; + let c in 0 .. 100; + let t in 0 .. 100; let period_begin = 1u32.into(); let period_count = 4u32.into(); diff --git a/runtime/kusama/Cargo.toml b/runtime/kusama/Cargo.toml index 63acb94e3e05..7770e8a6f7d8 100644 --- a/runtime/kusama/Cargo.toml +++ b/runtime/kusama/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "kusama-runtime" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" build = "build.rs" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } @@ -16,82 +16,81 @@ serde_derive = { version = "1.0.117", optional = true } static_assertions = "1.1.0" smallvec = "1.8.0" -authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, package = "sp-beefy" , branch = "polkadot-v0.9.36" } kusama-runtime-constants = { package = "kusama-runtime-constants", path = "./constants", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-arithmetic = { package = "sp-arithmetic", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-npos-elections = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-arithmetic = { package = "sp-arithmetic", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-npos-elections = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-bags-list = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-child-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-conviction-voting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-fast-unstake = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-gilt = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-identity = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-im-online = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-nomination-pools = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-ranked-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-recovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-referenda = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-society = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking-reward-fn = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system = {git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-tips = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-whitelist = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-bags-list = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-child-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-conviction-voting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-fast-unstake = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-nis = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-identity = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-im-online = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-nomination-pools = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-ranked-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-recovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-referenda = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-society = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system = {git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-tips = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-whitelist = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } pallet-xcm = { path = "../../xcm/pallet-xcm", default-features = false } pallet-xcm-benchmarks = { path = "../../xcm/pallet-xcm-benchmarks", default-features = false, optional = true } -frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-offences-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-session-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-nomination-pools-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-election-provider-support-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-offences-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-session-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-nomination-pools-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-election-provider-support-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } hex-literal = { version = "0.3.4", optional = true } runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false } @@ -105,16 +104,16 @@ xcm-builder = { package = "xcm-builder", path = "../../xcm/xcm-builder", default [dev-dependencies] hex-literal = "0.3.4" tiny-keccak = { version = "2.0.2", features = ["keccak"] } -keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } separator = "0.4.1" serde_json = "1.0.81" -remote-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -tokio = { version = "1.19.2", features = ["macros"] } -sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +remote-externalities = { git = "https://github.com/paritytech/substrate", package = "frame-remote-externalities" , branch = "polkadot-v0.9.36" } +tokio = { version = "1.22.0", features = ["macros"] } +sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = ["std"] @@ -151,7 +150,7 @@ std = [ "pallet-election-provider-multi-phase/std", "pallet-fast-unstake/std", "pallet-democracy/std", - "pallet-gilt/std", + "pallet-nis/std", "pallet-grandpa/std", "pallet-identity/std", "pallet-im-online/std", @@ -170,7 +169,6 @@ std = [ "pallet-session/std", "pallet-society/std", "pallet-staking/std", - "pallet-staking-reward-fn/std", "pallet-timestamp/std", "pallet-tips/std", "pallet-treasury/std", @@ -218,7 +216,7 @@ runtime-benchmarks = [ "pallet-election-provider-multi-phase/runtime-benchmarks", "pallet-election-provider-support-benchmarking/runtime-benchmarks", "pallet-fast-unstake/runtime-benchmarks", - "pallet-gilt/runtime-benchmarks", + "pallet-nis/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-identity/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", @@ -269,7 +267,7 @@ try-runtime = [ "pallet-election-provider-multi-phase/try-runtime", "pallet-fast-unstake/try-runtime", "pallet-democracy/try-runtime", - "pallet-gilt/try-runtime", + "pallet-nis/try-runtime", "pallet-grandpa/try-runtime", "pallet-identity/try-runtime", "pallet-im-online/try-runtime", diff --git a/runtime/kusama/constants/Cargo.toml b/runtime/kusama/constants/Cargo.toml index 7d8913f0025a..773dc8da9db7 100644 --- a/runtime/kusama/constants/Cargo.toml +++ b/runtime/kusama/constants/Cargo.toml @@ -1,18 +1,18 @@ [package] name = "kusama-runtime-constants" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] smallvec = "1.8.0" -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } primitives = { package = "polkadot-primitives", path = "../../../primitives", default-features = false } runtime-common = { package = "polkadot-runtime-common", path = "../../common", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-weights = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/runtime/kusama/constants/src/lib.rs b/runtime/kusama/constants/src/lib.rs index a8d047241b24..923f71b94dd8 100644 --- a/runtime/kusama/constants/src/lib.rs +++ b/runtime/kusama/constants/src/lib.rs @@ -26,8 +26,8 @@ pub mod currency { pub const EXISTENTIAL_DEPOSIT: Balance = 1 * CENTS; pub const UNITS: Balance = 1_000_000_000_000; - pub const CENTS: Balance = UNITS / 30_000; - pub const QUID: Balance = CENTS * 100; + pub const QUID: Balance = UNITS / 30; + pub const CENTS: Balance = QUID / 100; pub const GRAND: Balance = QUID * 1_000; pub const MILLICENTS: Balance = CENTS / 1_000; diff --git a/runtime/kusama/constants/src/weights/block_weights.rs b/runtime/kusama/constants/src/weights/block_weights.rs index cbe644d95629..adaf02eb138b 100644 --- a/runtime/kusama/constants/src/weights/block_weights.rs +++ b/runtime/kusama/constants/src/weights/block_weights.rs @@ -14,7 +14,7 @@ // 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: 2022-10-25 (Y/M/D) +//! DATE: 2022-12-16 (Y/M/D) //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `block`, LONG-NAME: `BlockExecution`, RUNTIME: `Development` @@ -35,23 +35,24 @@ // --header=./file_header.txt use sp_core::parameter_types; -use sp_weights::{constants::WEIGHT_PER_NANOS, Weight}; +use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; parameter_types! { /// Time to execute an empty block. /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 6_336_696, 6_629_376 - /// Average: 6_435_161 - /// Median: 6_432_853 - /// Std-Dev: 60191.34 + /// Min, Max: 6_685_216, 8_419_144 + /// Average: 6_866_800 + /// Median: 6_808_548 + /// Std-Dev: 272644.63 /// /// Percentiles nanoseconds: - /// 99th: 6_588_459 - /// 95th: 6_521_973 - /// 75th: 6_477_748 - pub const BlockExecutionWeight: Weight = WEIGHT_PER_NANOS.saturating_mul(6_435_161); + /// 99th: 8_064_831 + /// 95th: 7_116_548 + /// 75th: 6_856_386 + pub const BlockExecutionWeight: Weight = + Weight::from_ref_time(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(6_866_800)); } #[cfg(test)] @@ -67,12 +68,12 @@ mod test_weights { // At least 100 µs. assert!( - w.ref_time() >= 100u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 100 µs." ); // At most 50 ms. assert!( - w.ref_time() <= 50u64 * constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms." ); } diff --git a/runtime/kusama/constants/src/weights/extrinsic_weights.rs b/runtime/kusama/constants/src/weights/extrinsic_weights.rs index ee8c6b2fa50f..d9b6d1e36ed3 100644 --- a/runtime/kusama/constants/src/weights/extrinsic_weights.rs +++ b/runtime/kusama/constants/src/weights/extrinsic_weights.rs @@ -14,7 +14,7 @@ // 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: 2022-10-25 (Y/M/D) +//! DATE: 2022-12-16 (Y/M/D) //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `extrinsic`, LONG-NAME: `ExtrinsicBase`, RUNTIME: `Development` @@ -35,23 +35,24 @@ // --header=./file_header.txt use sp_core::parameter_types; -use sp_weights::{constants::WEIGHT_PER_NANOS, Weight}; +use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; parameter_types! { /// Time to execute a NO-OP extrinsic, for example `System::remark`. /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 95_139, 96_661 - /// Average: 95_578 - /// Median: 95_507 - /// Std-Dev: 279.89 + /// Min, Max: 95_632, 97_430 + /// Average: 96_247 + /// Median: 96_195 + /// Std-Dev: 376.91 /// /// Percentiles nanoseconds: - /// 99th: 96_641 - /// 95th: 96_239 - /// 75th: 95_630 - pub const ExtrinsicBaseWeight: Weight = WEIGHT_PER_NANOS.saturating_mul(95_578); + /// 99th: 97_334 + /// 95th: 97_055 + /// 75th: 96_444 + pub const ExtrinsicBaseWeight: Weight = + Weight::from_ref_time(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(96_247)); } #[cfg(test)] @@ -67,12 +68,12 @@ mod test_weights { // At least 10 µs. assert!( - w.ref_time() >= 10u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs." ); // At most 1 ms. assert!( - w.ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms." ); } diff --git a/runtime/kusama/constants/src/weights/paritydb_weights.rs b/runtime/kusama/constants/src/weights/paritydb_weights.rs index dca7d348310c..4338d928d807 100644 --- a/runtime/kusama/constants/src/weights/paritydb_weights.rs +++ b/runtime/kusama/constants/src/weights/paritydb_weights.rs @@ -25,8 +25,8 @@ pub mod constants { /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights /// are available for brave runtime engineers who may want to try this out as default. pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 8_000 * constants::WEIGHT_PER_NANOS.ref_time(), - write: 50_000 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 8_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 50_000 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -42,20 +42,20 @@ pub mod constants { fn sane() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/kusama/constants/src/weights/rocksdb_weights.rs b/runtime/kusama/constants/src/weights/rocksdb_weights.rs index 87867ebfe177..1d115d963fac 100644 --- a/runtime/kusama/constants/src/weights/rocksdb_weights.rs +++ b/runtime/kusama/constants/src/weights/rocksdb_weights.rs @@ -25,8 +25,8 @@ pub mod constants { /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout /// the runtime. pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 25_000 * constants::WEIGHT_PER_NANOS.ref_time(), - write: 100_000 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 25_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 100_000 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -42,20 +42,20 @@ pub mod constants { fn sane() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/kusama/src/governance/fellowship.rs b/runtime/kusama/src/governance/fellowship.rs index 52ab8d0bebc8..6d01780ebc0c 100644 --- a/runtime/kusama/src/governance/fellowship.rs +++ b/runtime/kusama/src/governance/fellowship.rs @@ -50,7 +50,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { prepare_period: 30 * MINUTES, decision_period: 7 * DAYS, confirm_period: 30 * MINUTES, - min_enactment_period: 4, + min_enactment_period: 1 * MINUTES, min_approval: pallet_referenda::Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), @@ -72,7 +72,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { prepare_period: 30 * MINUTES, decision_period: 7 * DAYS, confirm_period: 30 * MINUTES, - min_enactment_period: 4, + min_enactment_period: 1 * MINUTES, min_approval: pallet_referenda::Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), @@ -94,7 +94,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { prepare_period: 30 * MINUTES, decision_period: 7 * DAYS, confirm_period: 30 * MINUTES, - min_enactment_period: 4, + min_enactment_period: 1 * MINUTES, min_approval: pallet_referenda::Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), @@ -138,7 +138,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { prepare_period: 30 * MINUTES, decision_period: 7 * DAYS, confirm_period: 30 * MINUTES, - min_enactment_period: 4, + min_enactment_period: 1 * MINUTES, min_approval: pallet_referenda::Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), @@ -160,7 +160,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { prepare_period: 30 * MINUTES, decision_period: 7 * DAYS, confirm_period: 30 * MINUTES, - min_enactment_period: 4, + min_enactment_period: 1 * MINUTES, min_approval: pallet_referenda::Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), @@ -182,7 +182,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { prepare_period: 30 * MINUTES, decision_period: 7 * DAYS, confirm_period: 30 * MINUTES, - min_enactment_period: 4, + min_enactment_period: 1 * MINUTES, min_approval: pallet_referenda::Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), @@ -204,7 +204,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { prepare_period: 30 * MINUTES, decision_period: 7 * DAYS, confirm_period: 30 * MINUTES, - min_enactment_period: 4, + min_enactment_period: 1 * MINUTES, min_approval: pallet_referenda::Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), @@ -226,7 +226,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { prepare_period: 30 * MINUTES, decision_period: 7 * DAYS, confirm_period: 30 * MINUTES, - min_enactment_period: 4, + min_enactment_period: 1 * MINUTES, min_approval: pallet_referenda::Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), @@ -248,7 +248,7 @@ impl pallet_referenda::TracksInfo for TracksInfo { prepare_period: 30 * MINUTES, decision_period: 7 * DAYS, confirm_period: 30 * MINUTES, - min_enactment_period: 4, + min_enactment_period: 1 * MINUTES, min_approval: pallet_referenda::Curve::LinearDecreasing { length: Perbill::from_percent(100), floor: Perbill::from_percent(50), diff --git a/runtime/kusama/src/governance/mod.rs b/runtime/kusama/src/governance/mod.rs index 87cbfd7eea2f..3dd4eba2b57e 100644 --- a/runtime/kusama/src/governance/mod.rs +++ b/runtime/kusama/src/governance/mod.rs @@ -30,7 +30,7 @@ mod origins; pub use origins::{ pallet_custom_origins, AuctionAdmin, Fellows, FellowshipAdmin, FellowshipExperts, FellowshipInitiates, FellowshipMasters, GeneralAdmin, LeaseAdmin, ReferendumCanceller, - ReferendumKiller, Spender, StakingAdmin, WhitelistedCaller, + ReferendumKiller, Spender, StakingAdmin, Treasurer, WhitelistedCaller, }; mod tracks; pub use tracks::TracksInfo; @@ -47,14 +47,15 @@ impl pallet_conviction_voting::Config for Runtime { type Currency = Balances; type VoteLockingPeriod = VoteLockingPeriod; type MaxVotes = ConstU32<512>; - type MaxTurnout = frame_support::traits::TotalIssuanceOf; + type MaxTurnout = + frame_support::traits::tokens::currency::ActiveIssuanceOf; type Polls = Referenda; } parameter_types! { pub const AlarmInterval: BlockNumber = 1; - pub const SubmissionDeposit: Balance = 100 * UNITS; - pub const UndecidingTimeout: BlockNumber = 28 * DAYS; + pub const SubmissionDeposit: Balance = 1 * QUID; + pub const UndecidingTimeout: BlockNumber = 14 * DAYS; } parameter_types! { @@ -71,7 +72,7 @@ impl pallet_whitelist::Config for Runtime { type WhitelistOrigin = EitherOf>, Fellows>; type DispatchWhitelistedOrigin = EitherOf, WhitelistedCaller>; - type PreimageProvider = Preimage; + type Preimages = Preimage; } impl pallet_referenda::Config for Runtime { diff --git a/runtime/kusama/src/governance/origins.rs b/runtime/kusama/src/governance/origins.rs index be8c44430f46..b02ff53f3bab 100644 --- a/runtime/kusama/src/governance/origins.rs +++ b/runtime/kusama/src/governance/origins.rs @@ -120,6 +120,7 @@ pub mod pallet_custom_origins { } decl_unit_ensures!( StakingAdmin, + Treasurer, FellowshipAdmin, GeneralAdmin, AuctionAdmin, @@ -173,6 +174,7 @@ pub mod pallet_custom_origins { SmallSpender = 10 * GRAND, MediumSpender = 100 * GRAND, BigSpender = 1_000 * GRAND, + Treasurer = 10_000 * GRAND, } } diff --git a/runtime/kusama/src/governance/tracks.rs b/runtime/kusama/src/governance/tracks.rs index fd1c94118507..93b2312a76f8 100644 --- a/runtime/kusama/src/governance/tracks.rs +++ b/runtime/kusama/src/governance/tracks.rs @@ -63,7 +63,7 @@ const SUP_BIG_SPENDER: Curve = Curve::make_reciprocal(20, 28, percent(1), percen const APP_WHITELISTED_CALLER: Curve = Curve::make_reciprocal(16, 28 * 24, percent(96), percent(50), percent(100)); const SUP_WHITELISTED_CALLER: Curve = - Curve::make_reciprocal(1, 28, percent(20), percent(10), percent(50)); + Curve::make_reciprocal(1, 28, percent(20), percent(5), percent(50)); const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15] = [ ( @@ -71,11 +71,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 pallet_referenda::TrackInfo { name: "root", max_deciding: 1, - decision_deposit: 1_000 * GRAND, - prepare_period: 3 * HOURS, - decision_period: 28 * DAYS, - confirm_period: 3 * HOURS, - min_enactment_period: 3 * HOURS, + decision_deposit: 100 * GRAND, + prepare_period: 2 * HOURS, + decision_period: 14 * DAYS, + confirm_period: 24 * HOURS, + min_enactment_period: 24 * HOURS, min_approval: APP_ROOT, min_support: SUP_ROOT, }, @@ -84,12 +84,12 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 1, pallet_referenda::TrackInfo { name: "whitelisted_caller", - max_deciding: 10, - decision_deposit: 10_000 * GRAND, - prepare_period: 3 * HOURS, - decision_period: 28 * DAYS, + max_deciding: 100, + decision_deposit: 10 * GRAND, + prepare_period: 30 * MINUTES, + decision_period: 14 * DAYS, confirm_period: 10 * MINUTES, - min_enactment_period: 30 * MINUTES, + min_enactment_period: 10 * MINUTES, min_approval: APP_WHITELISTED_CALLER, min_support: SUP_WHITELISTED_CALLER, }, @@ -100,10 +100,10 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 name: "staking_admin", max_deciding: 10, decision_deposit: 5 * GRAND, - prepare_period: 4, - decision_period: 28 * DAYS, + prepare_period: 2 * HOURS, + decision_period: 14 * DAYS, confirm_period: 3 * HOURS, - min_enactment_period: 2 * DAYS, + min_enactment_period: 10 * MINUTES, min_approval: APP_STAKING_ADMIN, min_support: SUP_STAKING_ADMIN, }, @@ -113,11 +113,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 pallet_referenda::TrackInfo { name: "treasurer", max_deciding: 10, - decision_deposit: 5 * GRAND, - prepare_period: 4, - decision_period: 28 * DAYS, + decision_deposit: 1 * GRAND, + prepare_period: 2 * HOURS, + decision_period: 14 * DAYS, confirm_period: 3 * HOURS, - min_enactment_period: 2 * DAYS, + min_enactment_period: 24 * HOURS, min_approval: APP_TREASURER, min_support: SUP_TREASURER, }, @@ -128,10 +128,10 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 name: "lease_admin", max_deciding: 10, decision_deposit: 5 * GRAND, - prepare_period: 4, - decision_period: 28 * DAYS, + prepare_period: 2 * HOURS, + decision_period: 14 * DAYS, confirm_period: 3 * HOURS, - min_enactment_period: 2 * DAYS, + min_enactment_period: 10 * MINUTES, min_approval: APP_LEASE_ADMIN, min_support: SUP_LEASE_ADMIN, }, @@ -142,10 +142,10 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 name: "fellowship_admin", max_deciding: 10, decision_deposit: 5 * GRAND, - prepare_period: 4, - decision_period: 28 * DAYS, + prepare_period: 2 * HOURS, + decision_period: 14 * DAYS, confirm_period: 3 * HOURS, - min_enactment_period: 2 * DAYS, + min_enactment_period: 10 * MINUTES, min_approval: APP_FELLOWSHIP_ADMIN, min_support: SUP_FELLOWSHIP_ADMIN, }, @@ -156,10 +156,10 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 name: "general_admin", max_deciding: 10, decision_deposit: 5 * GRAND, - prepare_period: 4, - decision_period: 28 * DAYS, + prepare_period: 2 * HOURS, + decision_period: 14 * DAYS, confirm_period: 3 * HOURS, - min_enactment_period: 2 * DAYS, + min_enactment_period: 10 * MINUTES, min_approval: APP_GENERAL_ADMIN, min_support: SUP_GENERAL_ADMIN, }, @@ -170,10 +170,10 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 name: "auction_admin", max_deciding: 10, decision_deposit: 5 * GRAND, - prepare_period: 4, - decision_period: 28 * DAYS, + prepare_period: 2 * HOURS, + decision_period: 14 * DAYS, confirm_period: 3 * HOURS, - min_enactment_period: 2 * DAYS, + min_enactment_period: 10 * MINUTES, min_approval: APP_AUCTION_ADMIN, min_support: SUP_AUCTION_ADMIN, }, @@ -183,9 +183,9 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 pallet_referenda::TrackInfo { name: "referendum_canceller", max_deciding: 1_000, - decision_deposit: 50 * GRAND, - prepare_period: 4, - decision_period: 28 * DAYS, + decision_deposit: 10 * GRAND, + prepare_period: 2 * HOURS, + decision_period: 7 * DAYS, confirm_period: 3 * HOURS, min_enactment_period: 10 * MINUTES, min_approval: APP_REFERENDUM_CANCELLER, @@ -198,8 +198,8 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 name: "referendum_killer", max_deciding: 1_000, decision_deposit: 50 * GRAND, - prepare_period: 4, - decision_period: 28 * DAYS, + prepare_period: 2 * HOURS, + decision_period: 14 * DAYS, confirm_period: 3 * HOURS, min_enactment_period: 10 * MINUTES, min_approval: APP_REFERENDUM_KILLER, @@ -211,11 +211,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 pallet_referenda::TrackInfo { name: "small_tipper", max_deciding: 200, - decision_deposit: 5 * QUID, - prepare_period: 4, - decision_period: 28 * DAYS, - confirm_period: 3 * HOURS, - min_enactment_period: 28 * DAYS, + decision_deposit: 1 * QUID, + prepare_period: 1 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 10 * MINUTES, + min_enactment_period: 1 * MINUTES, min_approval: APP_SMALL_TIPPER, min_support: SUP_SMALL_TIPPER, }, @@ -225,11 +225,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 pallet_referenda::TrackInfo { name: "big_tipper", max_deciding: 100, - decision_deposit: 50 * QUID, - prepare_period: 4, - decision_period: 28 * DAYS, - confirm_period: 6 * HOURS, - min_enactment_period: 28 * DAYS, + decision_deposit: 10 * QUID, + prepare_period: 10 * MINUTES, + decision_period: 7 * DAYS, + confirm_period: 1 * HOURS, + min_enactment_period: 10 * MINUTES, min_approval: APP_BIG_TIPPER, min_support: SUP_BIG_TIPPER, }, @@ -239,11 +239,11 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 pallet_referenda::TrackInfo { name: "small_spender", max_deciding: 50, - decision_deposit: 500 * QUID, - prepare_period: 4, - decision_period: 28 * DAYS, + decision_deposit: 100 * QUID, + prepare_period: 4 * HOURS, + decision_period: 14 * DAYS, confirm_period: 12 * HOURS, - min_enactment_period: 28 * DAYS, + min_enactment_period: 24 * HOURS, min_approval: APP_SMALL_SPENDER, min_support: SUP_SMALL_SPENDER, }, @@ -252,12 +252,12 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 33, pallet_referenda::TrackInfo { name: "medium_spender", - max_deciding: 20, - decision_deposit: 1_500 * QUID, - prepare_period: 4, - decision_period: 28 * DAYS, + max_deciding: 50, + decision_deposit: 200 * QUID, + prepare_period: 4 * HOURS, + decision_period: 14 * DAYS, confirm_period: 24 * HOURS, - min_enactment_period: 28 * DAYS, + min_enactment_period: 24 * HOURS, min_approval: APP_MEDIUM_SPENDER, min_support: SUP_MEDIUM_SPENDER, }, @@ -266,12 +266,12 @@ const TRACKS_DATA: [(u16, pallet_referenda::TrackInfo); 15 34, pallet_referenda::TrackInfo { name: "big_spender", - max_deciding: 10, - decision_deposit: 5 * GRAND, - prepare_period: 4, - decision_period: 28 * DAYS, + max_deciding: 50, + decision_deposit: 400 * QUID, + prepare_period: 4 * HOURS, + decision_period: 14 * DAYS, confirm_period: 48 * HOURS, - min_enactment_period: 28 * DAYS, + min_enactment_period: 24 * HOURS, min_approval: APP_BIG_SPENDER, min_support: SUP_BIG_SPENDER, }, diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index 96ca53f680a6..e6ecb9b0df7a 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -20,12 +20,14 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit = "256"] +use pallet_nis::WithMaximumOf; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use primitives::v2::{ AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CommittedCandidateReceipt, CoreState, GroupRotationInfo, Hash, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, Moment, Nonce, OccupiedCoreAssumption, PersistedValidationData, ScrapedOnChainVotes, SessionInfo, Signature, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + LOWEST_PUBLIC_ID, }; use runtime_common::{ auctions, claims, crowdloan, impl_runtime_weights, impls::DealWithFees, paras_registrar, @@ -52,7 +54,7 @@ use frame_support::{ construct_runtime, parameter_types, traits::{ ConstU32, Contains, EitherOf, EitherOfDiverse, InstanceFilter, KeyOwnerProofSystem, - LockIdentifier, PrivilegeCmp, WithdrawReasons, + LockIdentifier, PrivilegeCmp, StorageMapShim, WithdrawReasons, }, weights::ConstantMultiplier, PalletId, RuntimeDebug, @@ -62,7 +64,7 @@ use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId}; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_session::historical as session_historical; use pallet_transaction_payment::{CurrencyAdapter, FeeDetails, RuntimeDispatchInfo}; -use sp_core::OpaqueMetadata; +use sp_core::{ConstU128, OpaqueMetadata}; use sp_mmr_primitives as mmr; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, @@ -105,8 +107,9 @@ pub mod xcm_config; pub mod governance; use governance::{ old::CouncilCollective, pallet_custom_origins, AuctionAdmin, GeneralAdmin, LeaseAdmin, - StakingAdmin, TreasurySpender, + StakingAdmin, Treasurer, TreasurySpender, }; +use xcm_config::CheckAccount; #[cfg(test)] mod tests; @@ -123,13 +126,13 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("kusama"), impl_name: create_runtime_str!("parity-kusama"), authoring_version: 2, - spec_version: 9310, + spec_version: 9360, impl_version: 0, #[cfg(not(feature = "disable-runtime-api"))] apis: RUNTIME_API_VERSIONS, #[cfg(feature = "disable-runtime-api")] apis: sp_version::create_apis_vec![[]], - transaction_version: 15, + transaction_version: 18, state_version: 0, }; @@ -410,6 +413,9 @@ parameter_types! { pub const MaxElectableTargets: u16 = u16::MAX; pub NposSolutionPriority: TransactionPriority = Perbill::from_percent(90) * TransactionPriority::max_value(); + /// Setup election pallet to support maximum winners upto 2000. This will mean Staking Pallet + /// cannot have active validators higher than this count. + pub const MaxActiveValidators: u32 = 2000; } generate_solution_type!( @@ -428,6 +434,9 @@ impl onchain::Config for OnChainSeqPhragmen { type Solver = SequentialPhragmen; type DataProvider = Staking; type WeightInfo = weights::frame_election_provider_support::WeightInfo; + type MaxWinners = MaxActiveValidators; + type VotersBound = MaxElectingVoters; + type TargetsBound = MaxElectableTargets; } impl pallet_election_provider_multi_phase::MinerConfig for Runtime { @@ -475,20 +484,26 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type MinerTxPriority = NposSolutionPriority; type DataProvider = Staking; #[cfg(feature = "fast-runtime")] - type Fallback = onchain::UnboundedExecution; + type Fallback = onchain::OnChainExecution; #[cfg(not(feature = "fast-runtime"))] - type Fallback = pallet_election_provider_multi_phase::NoFallback; - type GovernanceFallback = onchain::UnboundedExecution; + type Fallback = frame_election_provider_support::NoElection<( + AccountId, + BlockNumber, + Staking, + MaxActiveValidators, + )>; + type GovernanceFallback = onchain::OnChainExecution; type Solver = SequentialPhragmen< AccountId, pallet_election_provider_multi_phase::SolutionAccuracyOf, (), >; type BenchmarkingConfig = runtime_common::elections::BenchmarkConfig; - type ForceOrigin = StakingAdmin; + type ForceOrigin = EitherOf, StakingAdmin>; type WeightInfo = weights::pallet_election_provider_multi_phase::WeightInfo; type MaxElectingVoters = MaxElectingVoters; type MaxElectableTargets = MaxElectableTargets; + type MaxWinners = MaxActiveValidators; } parameter_types! { @@ -504,45 +519,6 @@ impl pallet_bags_list::Config for Runtime { type Score = sp_npos_elections::VoteWeight; } -fn era_payout( - total_staked: Balance, - non_gilt_issuance: Balance, - max_annual_inflation: Perquintill, - period_fraction: Perquintill, - auctioned_slots: u64, -) -> (Balance, Balance) { - use pallet_staking_reward_fn::compute_inflation; - use sp_arithmetic::traits::Saturating; - - let min_annual_inflation = Perquintill::from_rational(25u64, 1000u64); - let delta_annual_inflation = max_annual_inflation.saturating_sub(min_annual_inflation); - - // 30% reserved for up to 60 slots. - let auction_proportion = Perquintill::from_rational(auctioned_slots.min(60), 200u64); - - // Therefore the ideal amount at stake (as a percentage of total issuance) is 75% less the amount that we expect - // to be taken up with auctions. - let ideal_stake = Perquintill::from_percent(75).saturating_sub(auction_proportion); - - let stake = Perquintill::from_rational(total_staked, non_gilt_issuance); - let falloff = Perquintill::from_percent(5); - let adjustment = compute_inflation(stake, ideal_stake, falloff); - let staking_inflation = - min_annual_inflation.saturating_add(delta_annual_inflation * adjustment); - - let max_payout = period_fraction * max_annual_inflation * non_gilt_issuance; - let staking_payout = (period_fraction * staking_inflation) * non_gilt_issuance; - let rest = max_payout.saturating_sub(staking_payout); - - let other_issuance = non_gilt_issuance.saturating_sub(total_staked); - if total_staked > other_issuance { - let _cap_rest = Perquintill::from_rational(other_issuance, total_staked) * staking_payout; - // We don't do anything with this, but if we wanted to, we could introduce a cap on the treasury amount - // with: `rest = rest.min(cap_rest);` - } - (staking_payout, rest) -} - pub struct EraPayout; impl pallet_staking::EraPayout for EraPayout { fn era_payout( @@ -550,15 +526,20 @@ impl pallet_staking::EraPayout for EraPayout { _total_issuance: Balance, era_duration_millis: u64, ) -> (Balance, Balance) { - // TODO: #3011 Update with proper auctioned slots tracking. - // This should be fine for the first year of parachains. - let auctioned_slots: u64 = auctions::Pallet::::auction_counter().into(); + // all para-ids that are currently active. + let auctioned_slots = Paras::parachains() + .into_iter() + // all active para-ids that do not belong to a system or common good chain is the number + // of parachains that we should take into account for inflation. + .filter(|i| *i >= LOWEST_PUBLIC_ID) + .count() as u64; + const MAX_ANNUAL_INFLATION: Perquintill = Perquintill::from_percent(10); const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100; - era_payout( + runtime_common::impls::era_payout( total_staked, - Gilt::issuance().non_gilt, + Nis::issuance().other, MAX_ANNUAL_INFLATION, Perquintill::from_rational(era_duration_millis, MILLISECONDS_PER_YEAR), auctioned_slots, @@ -569,11 +550,20 @@ impl pallet_staking::EraPayout for EraPayout { parameter_types! { // Six sessions in an era (6 hours). pub const SessionsPerEra: SessionIndex = prod_or_fast!(6, 1); + // 28 eras for unbonding (7 days). - pub const BondingDuration: sp_staking::EraIndex = 28; + pub BondingDuration: sp_staking::EraIndex = prod_or_fast!( + 28, + 28, + "DOT_BONDING_DURATION" + ); // 27 eras in which slashes can be cancelled (slightly less than 7 days). - pub const SlashDeferDuration: sp_staking::EraIndex = 27; - pub const MaxNominatorRewardedPerValidator: u32 = 256; + pub SlashDeferDuration: sp_staking::EraIndex = prod_or_fast!( + 27, + 27, + "DOT_SLASH_DEFER_DURATION" + ); + pub const MaxNominatorRewardedPerValidator: u32 = 512; pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); // 24 pub const MaxNominations: u32 = ::LIMIT as u32; @@ -586,7 +576,7 @@ impl pallet_staking::Config for Runtime { type UnixTime = Timestamp; type CurrencyToVote = CurrencyToVote; type ElectionProvider = ElectionProviderMultiPhase; - type GenesisElectionProvider = onchain::UnboundedExecution; + type GenesisElectionProvider = onchain::OnChainExecution; type RewardRemainder = Treasury; type RuntimeEvent = RuntimeEvent; type Slash = Treasury; @@ -612,13 +602,15 @@ impl pallet_staking::Config for Runtime { impl pallet_fast_unstake::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type DepositCurrency = Balances; + type Currency = Balances; + type BatchSize = frame_support::traits::ConstU32<64>; type Deposit = frame_support::traits::ConstU128<{ CENTS * 100 }>; type ControlOrigin = EitherOfDiverse< EnsureRoot, pallet_collective::EnsureProportionAtLeast, >; type WeightInfo = weights::pallet_fast_unstake::WeightInfo; + type Staking = Staking; } parameter_types! { @@ -643,8 +635,8 @@ parameter_types! { impl pallet_treasury::Config for Runtime { type PalletId = TreasuryPalletId; type Currency = Balances; - type ApproveOrigin = EnsureRoot; - type RejectOrigin = EnsureRoot; + type ApproveOrigin = EitherOfDiverse, Treasurer>; + type RejectOrigin = EitherOfDiverse, Treasurer>; type RuntimeEvent = RuntimeEvent; type OnSlash = Treasury; type ProposalBond = ProposalBond; @@ -851,8 +843,8 @@ impl pallet_identity::Config for Runtime { type MaxAdditionalFields = MaxAdditionalFields; type MaxRegistrars = MaxRegistrars; type Slashed = Treasury; - type ForceOrigin = GeneralAdmin; - type RegistrarOrigin = GeneralAdmin; + type ForceOrigin = EitherOf, GeneralAdmin>; + type RegistrarOrigin = EitherOf, GeneralAdmin>; type WeightInfo = weights::pallet_identity::WeightInfo; } @@ -868,7 +860,7 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); - pub const MaxSignatories: u16 = 100; + pub const MaxSignatories: u32 = 100; } impl pallet_multisig::Config for Runtime { @@ -1015,6 +1007,11 @@ impl InstanceFilter for ProxyType { RuntimeCall::Bounties(..) | RuntimeCall::ChildBounties(..) | RuntimeCall::Tips(..) | + RuntimeCall::ConvictionVoting(..) | + RuntimeCall::Referenda(..) | + RuntimeCall::FellowshipCollective(..) | + RuntimeCall::FellowshipReferenda(..) | + RuntimeCall::Whitelist(..) | RuntimeCall::Claims(..) | RuntimeCall::Utility(..) | RuntimeCall::Identity(..) | @@ -1032,7 +1029,7 @@ impl InstanceFilter for ProxyType { RuntimeCall::Scheduler(..) | RuntimeCall::Proxy(..) | RuntimeCall::Multisig(..) | - RuntimeCall::Gilt(..) | + RuntimeCall::Nis(..) | RuntimeCall::Registrar(paras_registrar::Call::register {..}) | RuntimeCall::Registrar(paras_registrar::Call::deregister {..}) | // Specifically omitting Registrar `swap` @@ -1044,17 +1041,22 @@ impl InstanceFilter for ProxyType { RuntimeCall::NominationPools(..) | RuntimeCall::FastUnstake(..) ), - ProxyType::Governance => - matches!( - c, - RuntimeCall::Democracy(..) | - RuntimeCall::Council(..) | RuntimeCall::TechnicalCommittee(..) | - RuntimeCall::PhragmenElection(..) | - RuntimeCall::Treasury(..) | - RuntimeCall::Bounties(..) | - RuntimeCall::Tips(..) | RuntimeCall::Utility(..) | - RuntimeCall::ChildBounties(..) - ), + ProxyType::Governance => matches!( + c, + RuntimeCall::Democracy(..) | + RuntimeCall::Council(..) | RuntimeCall::TechnicalCommittee(..) | + RuntimeCall::PhragmenElection(..) | + RuntimeCall::Treasury(..) | + RuntimeCall::Bounties(..) | + RuntimeCall::Tips(..) | RuntimeCall::Utility(..) | + RuntimeCall::ChildBounties(..) | + // OpenGov calls + RuntimeCall::ConvictionVoting(..) | + RuntimeCall::Referenda(..) | + RuntimeCall::FellowshipCollective(..) | + RuntimeCall::FellowshipReferenda(..) | + RuntimeCall::Whitelist(..) + ), ProxyType::Staking => { matches!( c, @@ -1202,7 +1204,7 @@ impl slots::Config for Runtime { type Registrar = Registrar; type LeasePeriod = LeasePeriod; type LeaseOffset = (); - type ForceOrigin = LeaseAdmin; + type ForceOrigin = EitherOf, LeaseAdmin>; type WeightInfo = weights::runtime_common_slots::WeightInfo; } @@ -1242,37 +1244,61 @@ impl auctions::Config for Runtime { type EndingPeriod = EndingPeriod; type SampleLength = SampleLength; type Randomness = pallet_babe::RandomnessFromOneEpochAgo; - type InitiateOrigin = AuctionAdmin; + type InitiateOrigin = EitherOf, AuctionAdmin>; type WeightInfo = weights::runtime_common_auctions::WeightInfo; } +type NisCounterpartInstance = pallet_balances::Instance2; +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU128<10_000_000_000>; // One KTC cent + type AccountStore = StorageMapShim< + pallet_balances::Account, + frame_system::Provider, + AccountId, + pallet_balances::AccountData, + >; + type MaxLocks = ConstU32<4>; + type MaxReserves = ConstU32<4>; + type ReserveIdentifier = [u8; 8]; + type WeightInfo = weights::pallet_balances_nis_counterpart_balances::WeightInfo; +} + parameter_types! { pub IgnoredIssuance: Balance = Treasury::pot(); - pub const QueueCount: u32 = 300; - pub const MaxQueueLen: u32 = 1000; - pub const FifoQueueLen: u32 = 250; - pub const GiltPeriod: BlockNumber = 30 * DAYS; - pub const MinFreeze: Balance = 10_000 * CENTS; + pub const NisBasePeriod: BlockNumber = 7 * DAYS; + pub const MinBid: Balance = 100 * QUID; + pub MinReceipt: Perquintill = Perquintill::from_rational(1u64, 10_000_000u64); pub const IntakePeriod: BlockNumber = 5 * MINUTES; - pub const MaxIntakeBids: u32 = 100; + pub MaxIntakeWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10; + pub const ThawThrottle: (Perquintill, BlockNumber) = (Perquintill::from_percent(25), 5); + pub storage NisTarget: Perquintill = Perquintill::zero(); + pub const NisPalletId: PalletId = PalletId(*b"py/nis "); } -impl pallet_gilt::Config for Runtime { +impl pallet_nis::Config for Runtime { + type WeightInfo = weights::pallet_nis::WeightInfo; type RuntimeEvent = RuntimeEvent; type Currency = Balances; type CurrencyBalance = Balance; - type AdminOrigin = EnsureRoot; + type FundOrigin = frame_system::EnsureSigned; + type Counterpart = NisCounterpartBalances; + type CounterpartAmount = WithMaximumOf>; type Deficit = (); // Mint - type Surplus = (); // Burn type IgnoredIssuance = IgnoredIssuance; - type QueueCount = QueueCount; - type MaxQueueLen = MaxQueueLen; - type FifoQueueLen = FifoQueueLen; - type Period = GiltPeriod; - type MinFreeze = MinFreeze; + type Target = NisTarget; + type PalletId = NisPalletId; + type QueueCount = ConstU32<500>; + type MaxQueueLen = ConstU32<1000>; + type FifoQueueLen = ConstU32<250>; + type BasePeriod = NisBasePeriod; + type MinBid = MinBid; + type MinReceipt = MinReceipt; type IntakePeriod = IntakePeriod; - type MaxIntakeBids = MaxIntakeBids; - type WeightInfo = weights::pallet_gilt::WeightInfo; + type MaxIntakeWeight = MaxIntakeWeight; + type ThawThrottle = ThawThrottle; } parameter_types! { @@ -1284,11 +1310,10 @@ impl pallet_nomination_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = weights::pallet_nomination_pools::WeightInfo; type Currency = Balances; - type CurrencyBalance = Balance; type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; - type StakingInterface = Staking; + type Staking = Staking; type PostUnbondingPoolsWindow = ConstU32<4>; type MaxMetadataLen = ConstU32<256>; // we use the same number of allowed unlocking chunks as with staking. @@ -1387,8 +1412,10 @@ construct_runtime! { // Election pallet. Only works with staking, but placed here to maintain indices. ElectionProviderMultiPhase: pallet_election_provider_multi_phase::{Pallet, Call, Storage, Event, ValidateUnsigned} = 37, - // Gilts pallet. - Gilt: pallet_gilt::{Pallet, Call, Storage, Event, Config} = 38, + // NIS pallet. + Nis: pallet_nis::{Pallet, Call, Storage, Event} = 38, +// pub type NisCounterpartInstance = pallet_balances::Instance2; + NisCounterpartBalances: pallet_balances:: = 45, // Provides a semi-sorted list of nominators for staking. VoterList: pallet_bags_list::::{Pallet, Call, Storage, Event} = 39, @@ -1454,6 +1481,8 @@ impl Get<&'static str> for StakingMigrationV11OldPallet { } } +pub type Migrations = (); + /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; @@ -1464,15 +1493,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - ( - // "Bound uses of call" - pallet_preimage::migration::v1::Migration, - pallet_scheduler::migration::v3::MigrateToV4, - pallet_democracy::migrations::v1::Migration, - pallet_multisig::migrations::v1::MigrateToV1, - // "Properly migrate weights to v2" - parachains_configuration::migration::v3::MigrateToV3, - ), + Migrations, >; /// The payload being signed in the transactions. pub type SignedPayload = generic::SignedPayload; @@ -1486,7 +1507,7 @@ mod benches { define_benchmarks!( // Polkadot // NOTE: Make sure to prefix these with `runtime_common::` so - // the that path resolves correctly in the generated file. + // that the path resolves correctly in the generated file. [runtime_common::auctions, Auctions] [runtime_common::crowdloan, Crowdloan] [runtime_common::claims, Claims] @@ -1501,6 +1522,7 @@ mod benches { [runtime_parachains::ump, Ump] // Substrate [pallet_balances, Balances] + [pallet_balances, NisCounterpartBalances] [pallet_bags_list, VoterList] [frame_benchmarking::baseline, Baseline::] [pallet_bounties, Bounties] @@ -1513,7 +1535,7 @@ mod benches { [pallet_election_provider_multi_phase, ElectionProviderMultiPhase] [frame_election_provider_support, ElectionProviderBench::] [pallet_fast_unstake, FastUnstake] - [pallet_gilt, Gilt] + [pallet_nis, Nis] [pallet_identity, Identity] [pallet_im_online, ImOnline] [pallet_indices, Indices] @@ -1709,53 +1731,31 @@ sp_api::impl_runtime_apis! { } impl mmr::MmrApi for Runtime { - fn generate_proof(_block_number: BlockNumber) - -> Result<(mmr::EncodableOpaqueLeaf, mmr::Proof), mmr::Error> - { - Err(mmr::Error::PalletNotIncluded) - } - - fn verify_proof(_leaf: mmr::EncodableOpaqueLeaf, _proof: mmr::Proof) - -> Result<(), mmr::Error> - { - Err(mmr::Error::PalletNotIncluded) - } - - fn verify_proof_stateless( - _root: Hash, - _leaf: mmr::EncodableOpaqueLeaf, - _proof: mmr::Proof - ) -> Result<(), mmr::Error> { - Err(mmr::Error::PalletNotIncluded) - } - fn mmr_root() -> Result { Err(mmr::Error::PalletNotIncluded) } - fn generate_batch_proof(_block_numbers: Vec) - -> Result<(Vec, mmr::BatchProof), mmr::Error> - { + fn mmr_leaf_count() -> Result { Err(mmr::Error::PalletNotIncluded) } - fn generate_historical_batch_proof( + fn generate_proof( _block_numbers: Vec, - _best_known_block_number: BlockNumber, - ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { + _best_known_block_number: Option, + ) -> Result<(Vec, mmr::Proof), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_batch_proof(_leaves: Vec, _proof: mmr::BatchProof) + fn verify_proof(_leaves: Vec, _proof: mmr::Proof) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_batch_proof_stateless( + fn verify_proof_stateless( _root: Hash, _leaves: Vec, - _proof: mmr::BatchProof + _proof: mmr::Proof ) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } @@ -1905,21 +1905,21 @@ sp_api::impl_runtime_apis! { #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { - fn on_runtime_upgrade() -> (Weight, Weight) { + fn on_runtime_upgrade(checks: bool) -> (Weight, Weight) { log::info!("try-runtime::on_runtime_upgrade kusama."); - let weight = Executive::try_runtime_upgrade().unwrap(); + let weight = Executive::try_runtime_upgrade(checks).unwrap(); (weight, BlockWeights::get().max_block) } - fn execute_block(block: Block, state_root_check: bool, select: frame_try_runtime::TryStateSelect) -> Weight { - log::info!( - target: "runtime::kusama", "try-runtime: executing block #{} ({:?}) / root checks: {:?} / sanity-checks: {:?}", - block.header.number, - block.header.hash(), - state_root_check, - select, - ); - Executive::try_execute_block(block, state_root_check, select).expect("try_execute_block failed") + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect, + ) -> Weight { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. + Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() } } @@ -2074,14 +2074,14 @@ mod tests_fess { // ensure this number does not change, or that it is checked after each change. // a 1 MB solution should need around 0.16 KSM deposit let deposit = SignedDepositBase::get() + (SignedDepositByte::get() * 1024 * 1024); - assert_eq_error_rate!(deposit, UNITS * 16 / 100, UNITS / 100); + assert_eq_error_rate!(deposit, UNITS * 167 / 100, UNITS / 100); } } #[cfg(test)] mod multiplier_tests { use super::*; - use frame_support::{dispatch::GetDispatchInfo, traits::OnFinalize}; + use frame_support::{dispatch::DispatchInfo, traits::OnFinalize}; use runtime_common::{MinimumMultiplier, TargetBlockFullness}; use separator::Separatable; use sp_runtime::traits::Convert; @@ -2123,17 +2123,8 @@ mod multiplier_tests { let mut blocks = 0; let mut fees_paid = 0; - let call = frame_system::Call::::fill_block { - ratio: Perbill::from_rational( - block_weight.ref_time(), - BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap().ref_time(), - ), - }; - println!("calling {:?}", call); - let info = call.get_dispatch_info(); - // convert to outer call. - let call = RuntimeCall::System(call); - let len = call.using_encoded(|e| e.len()) as u32; + frame_system::Pallet::::set_block_consumed_resources(Weight::MAX, 0); + let info = DispatchInfo { weight: Weight::MAX, ..Default::default() }; let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::default() .build_storage::() @@ -2147,7 +2138,7 @@ mod multiplier_tests { while multiplier <= Multiplier::from_u32(1) { t.execute_with(|| { // imagine this tx was called. - let fee = TransactionPayment::compute_fee(len, &info, 0); + let fee = TransactionPayment::compute_fee(0, &info, 0); fees_paid += fee; // this will update the multiplier. @@ -2234,6 +2225,6 @@ mod remote_tests { .build() .await .unwrap(); - ext.execute_with(|| Runtime::on_runtime_upgrade()); + ext.execute_with(|| Runtime::on_runtime_upgrade(true)); } } diff --git a/runtime/kusama/src/tests.rs b/runtime/kusama/src/tests.rs index 12d02da131f8..ef09a9dc6131 100644 --- a/runtime/kusama/src/tests.rs +++ b/runtime/kusama/src/tests.rs @@ -137,40 +137,6 @@ fn nominator_limit() { println!("can support {} nominators to yield a weight of {}", active, weight_with(active)); } -#[test] -fn compute_inflation_should_give_sensible_results() { - assert_eq!( - pallet_staking_reward_fn::compute_inflation( - Perquintill::from_percent(75), - Perquintill::from_percent(75), - Perquintill::from_percent(5), - ), - Perquintill::one() - ); - assert_eq!( - pallet_staking_reward_fn::compute_inflation( - Perquintill::from_percent(50), - Perquintill::from_percent(75), - Perquintill::from_percent(5), - ), - Perquintill::from_rational(2u64, 3u64) - ); - assert_eq!( - pallet_staking_reward_fn::compute_inflation( - Perquintill::from_percent(80), - Perquintill::from_percent(75), - Perquintill::from_percent(5), - ), - Perquintill::from_rational(1u64, 2u64) - ); -} - -#[test] -fn era_payout_should_give_sensible_results() { - assert_eq!(era_payout(75, 100, Perquintill::from_percent(10), Perquintill::one(), 0,), (10, 0)); - assert_eq!(era_payout(80, 100, Perquintill::from_percent(10), Perquintill::one(), 0,), (6, 4)); -} - #[test] fn call_size() { RuntimeCall::assert_size_under(230); diff --git a/runtime/kusama/src/weights/frame_benchmarking_baseline.rs b/runtime/kusama/src/weights/frame_benchmarking_baseline.rs index 510238204622..26ae9bdb3f3c 100644 --- a/runtime/kusama/src/weights/frame_benchmarking_baseline.rs +++ b/runtime/kusama/src/weights/frame_benchmarking_baseline.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_benchmarking::baseline` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -46,54 +46,54 @@ pub struct WeightInfo(PhantomData); impl frame_benchmarking::baseline::WeightInfo for WeightInfo { /// The range of component `i` is `[0, 1000000]`. fn addition(_i: u32, ) -> Weight { - // Minimum execution time: 86 nanoseconds. - Weight::from_ref_time(102_920 as u64) + // Minimum execution time: 136 nanoseconds. + Weight::from_ref_time(166_415) } /// The range of component `i` is `[0, 1000000]`. fn subtraction(_i: u32, ) -> Weight { - // Minimum execution time: 93 nanoseconds. - Weight::from_ref_time(110_716 as u64) + // Minimum execution time: 134 nanoseconds. + Weight::from_ref_time(157_476) } /// The range of component `i` is `[0, 1000000]`. fn multiplication(_i: u32, ) -> Weight { - // Minimum execution time: 97 nanoseconds. - Weight::from_ref_time(121_613 as u64) + // Minimum execution time: 146 nanoseconds. + Weight::from_ref_time(181_850) } /// The range of component `i` is `[0, 1000000]`. fn division(_i: u32, ) -> Weight { - // Minimum execution time: 85 nanoseconds. - Weight::from_ref_time(108_770 as u64) + // Minimum execution time: 138 nanoseconds. + Weight::from_ref_time(160_267) } /// The range of component `i` is `[0, 100]`. fn hashing(i: u32, ) -> Weight { - // Minimum execution time: 19_096_918 nanoseconds. - Weight::from_ref_time(19_341_958_891 as u64) - // Standard Error: 136_508 - .saturating_add(Weight::from_ref_time(347_531 as u64).saturating_mul(i as u64)) + // Minimum execution time: 20_402_851 nanoseconds. + Weight::from_ref_time(20_598_144_604) + // Standard Error: 170_002 + .saturating_add(Weight::from_ref_time(1_774_395).saturating_mul(i.into())) } /// The range of component `i` is `[0, 100]`. fn sr25519_verification(i: u32, ) -> Weight { - // Minimum execution time: 111 nanoseconds. - Weight::from_ref_time(118_000 as u64) - // Standard Error: 16_773 - .saturating_add(Weight::from_ref_time(47_757_384 as u64).saturating_mul(i as u64)) + // Minimum execution time: 172 nanoseconds. + Weight::from_ref_time(184_000) + // Standard Error: 15_734 + .saturating_add(Weight::from_ref_time(47_361_013).saturating_mul(i.into())) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn storage_read(i: u32, ) -> Weight { - // Minimum execution time: 94 nanoseconds. - Weight::from_ref_time(97_000 as u64) - // Standard Error: 3_564 - .saturating_add(Weight::from_ref_time(1_832_717 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 153 nanoseconds. + Weight::from_ref_time(158_000) + // Standard Error: 3_447 + .saturating_add(Weight::from_ref_time(1_943_306).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn storage_write(i: u32, ) -> Weight { - // Minimum execution time: 111 nanoseconds. - Weight::from_ref_time(119_000 as u64) - // Standard Error: 812 - .saturating_add(Weight::from_ref_time(320_377 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 156 nanoseconds. + Weight::from_ref_time(165_000) + // Standard Error: 826 + .saturating_add(Weight::from_ref_time(339_692).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } } diff --git a/runtime/kusama/src/weights/frame_election_provider_support.rs b/runtime/kusama/src/weights/frame_election_provider_support.rs index 82bf4f3cfa20..e87e6d18f9a4 100644 --- a/runtime/kusama/src/weights/frame_election_provider_support.rs +++ b/runtime/kusama/src/weights/frame_election_provider_support.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_election_provider_support` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -48,22 +48,22 @@ impl frame_election_provider_support::WeightInfo for We /// The range of component `t` is `[500, 1000]`. /// The range of component `d` is `[5, 16]`. fn phragmen(v: u32, _t: u32, d: u32, ) -> Weight { - // Minimum execution time: 5_442_855 nanoseconds. - Weight::from_ref_time(5_493_581_000 as u64) - // Standard Error: 137_072 - .saturating_add(Weight::from_ref_time(5_644_474 as u64).saturating_mul(v as u64)) - // Standard Error: 14_013_799 - .saturating_add(Weight::from_ref_time(1_560_631_740 as u64).saturating_mul(d as u64)) + // Minimum execution time: 5_604_066 nanoseconds. + Weight::from_ref_time(5_684_602_000) + // Standard Error: 136_652 + .saturating_add(Weight::from_ref_time(5_624_974).saturating_mul(v.into())) + // Standard Error: 13_970_853 + .saturating_add(Weight::from_ref_time(1_542_520_189).saturating_mul(d.into())) } /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `d` is `[5, 16]`. fn phragmms(v: u32, _t: u32, d: u32, ) -> Weight { - // Minimum execution time: 4_312_432 nanoseconds. - Weight::from_ref_time(4_352_242_000 as u64) - // Standard Error: 147_368 - .saturating_add(Weight::from_ref_time(5_532_148 as u64).saturating_mul(v as u64)) - // Standard Error: 15_066_445 - .saturating_add(Weight::from_ref_time(1_788_360_934 as u64).saturating_mul(d as u64)) + // Minimum execution time: 4_388_357 nanoseconds. + Weight::from_ref_time(4_435_501_000) + // Standard Error: 144_834 + .saturating_add(Weight::from_ref_time(5_517_220).saturating_mul(v.into())) + // Standard Error: 14_807_411 + .saturating_add(Weight::from_ref_time(1_743_460_054).saturating_mul(d.into())) } } diff --git a/runtime/kusama/src/weights/frame_system.rs b/runtime/kusama/src/weights/frame_system.rs index d3797e9c2a4c..41eefdd60edf 100644 --- a/runtime/kusama/src/weights/frame_system.rs +++ b/runtime/kusama/src/weights/frame_system.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_system` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -46,51 +46,51 @@ pub struct WeightInfo(PhantomData); impl frame_system::WeightInfo for WeightInfo { /// The range of component `b` is `[0, 3932160]`. fn remark(b: u32, ) -> Weight { - // Minimum execution time: 3_048 nanoseconds. - Weight::from_ref_time(3_101_000 as u64) + // Minimum execution time: 3_648 nanoseconds. + Weight::from_ref_time(3_683_000) // Standard Error: 0 - .saturating_add(Weight::from_ref_time(411 as u64).saturating_mul(b as u64)) + .saturating_add(Weight::from_ref_time(411).saturating_mul(b.into())) } /// The range of component `b` is `[0, 3932160]`. fn remark_with_event(b: u32, ) -> Weight { - // Minimum execution time: 11_933 nanoseconds. - Weight::from_ref_time(12_021_000 as u64) + // Minimum execution time: 13_146 nanoseconds. + Weight::from_ref_time(13_225_000) // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_728 as u64).saturating_mul(b as u64)) + .saturating_add(Weight::from_ref_time(1_768).saturating_mul(b.into())) } // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - // Minimum execution time: 7_187 nanoseconds. - Weight::from_ref_time(7_397_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 8_585 nanoseconds. + Weight::from_ref_time(8_945_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { - // Minimum execution time: 2_999 nanoseconds. - Weight::from_ref_time(3_090_000 as u64) - // Standard Error: 2_241 - .saturating_add(Weight::from_ref_time(608_495 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 3_544 nanoseconds. + Weight::from_ref_time(3_627_000) + // Standard Error: 2_039 + .saturating_add(Weight::from_ref_time(627_800).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { - // Minimum execution time: 3_015 nanoseconds. - Weight::from_ref_time(3_067_000 as u64) - // Standard Error: 934 - .saturating_add(Weight::from_ref_time(436_860 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 3_552 nanoseconds. + Weight::from_ref_time(3_643_000) + // Standard Error: 931 + .saturating_add(Weight::from_ref_time(448_561).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { - // Minimum execution time: 4_577 nanoseconds. - Weight::from_ref_time(4_711_000 as u64) - // Standard Error: 1_234 - .saturating_add(Weight::from_ref_time(935_778 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 5_388 nanoseconds. + Weight::from_ref_time(5_462_000) + // Standard Error: 1_167 + .saturating_add(Weight::from_ref_time(968_196).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } } diff --git a/runtime/kusama/src/weights/mod.rs b/runtime/kusama/src/weights/mod.rs index 2f9e2d35c211..c277b2beb819 100644 --- a/runtime/kusama/src/weights/mod.rs +++ b/runtime/kusama/src/weights/mod.rs @@ -19,6 +19,7 @@ pub mod frame_election_provider_support; pub mod frame_system; pub mod pallet_bags_list; pub mod pallet_balances; +pub mod pallet_balances_nis_counterpart_balances; pub mod pallet_bounties; pub mod pallet_child_bounties; pub mod pallet_collective_council; @@ -28,12 +29,12 @@ pub mod pallet_democracy; pub mod pallet_election_provider_multi_phase; pub mod pallet_elections_phragmen; pub mod pallet_fast_unstake; -pub mod pallet_gilt; pub mod pallet_identity; pub mod pallet_im_online; pub mod pallet_indices; pub mod pallet_membership; pub mod pallet_multisig; +pub mod pallet_nis; pub mod pallet_nomination_pools; pub mod pallet_preimage; pub mod pallet_proxy; diff --git a/runtime/kusama/src/weights/pallet_bags_list.rs b/runtime/kusama/src/weights/pallet_bags_list.rs index bc230a6226ec..e971db995843 100644 --- a/runtime/kusama/src/weights/pallet_bags_list.rs +++ b/runtime/kusama/src/weights/pallet_bags_list.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_bags_list` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -49,20 +49,20 @@ impl pallet_bags_list::WeightInfo for WeightInfo { // Storage: VoterList ListNodes (r:4 w:4) // Storage: VoterList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - // Minimum execution time: 59_649 nanoseconds. - Weight::from_ref_time(60_237_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 66_208 nanoseconds. + Weight::from_ref_time(66_877_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - // Minimum execution time: 59_000 nanoseconds. - Weight::from_ref_time(60_766_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 64_493 nanoseconds. + Weight::from_ref_time(65_068_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: VoterList ListNodes (r:4 w:4) // Storage: Staking Bonded (r:2 w:0) @@ -70,9 +70,9 @@ impl pallet_bags_list::WeightInfo for WeightInfo { // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: VoterList ListBags (r:1 w:1) fn put_in_front_of() -> Weight { - // Minimum execution time: 58_720 nanoseconds. - Weight::from_ref_time(59_461_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 64_542 nanoseconds. + Weight::from_ref_time(65_395_000) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(6)) } } diff --git a/runtime/kusama/src/weights/pallet_balances.rs b/runtime/kusama/src/weights/pallet_balances.rs index 79cc02b8bce0..1787c8d3822d 100644 --- a/runtime/kusama/src/weights/pallet_balances.rs +++ b/runtime/kusama/src/weights/pallet_balances.rs @@ -16,8 +16,8 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! DATE: 2022-11-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 // Executed Command: @@ -46,50 +46,50 @@ pub struct WeightInfo(PhantomData); impl pallet_balances::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - // Minimum execution time: 38_597 nanoseconds. - Weight::from_ref_time(39_341_000 as u64) + // Minimum execution time: 40_902 nanoseconds. + Weight::from_ref_time(41_638_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - // Minimum execution time: 30_016 nanoseconds. - Weight::from_ref_time(30_522_000 as u64) + // Minimum execution time: 30_093 nanoseconds. + Weight::from_ref_time(30_732_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - // Minimum execution time: 22_114 nanoseconds. - Weight::from_ref_time(22_750_000 as u64) + // Minimum execution time: 23_901 nanoseconds. + Weight::from_ref_time(24_238_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - // Minimum execution time: 24_939 nanoseconds. - Weight::from_ref_time(25_606_000 as u64) + // Minimum execution time: 26_402 nanoseconds. + Weight::from_ref_time(27_026_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:2 w:2) fn force_transfer() -> Weight { - // Minimum execution time: 38_778 nanoseconds. - Weight::from_ref_time(39_589_000 as u64) + // Minimum execution time: 40_328 nanoseconds. + Weight::from_ref_time(41_242_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - // Minimum execution time: 34_069 nanoseconds. - Weight::from_ref_time(34_876_000 as u64) + // Minimum execution time: 35_401 nanoseconds. + Weight::from_ref_time(36_122_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - // Minimum execution time: 19_270 nanoseconds. - Weight::from_ref_time(19_675_000 as u64) + // Minimum execution time: 20_178 nanoseconds. + Weight::from_ref_time(20_435_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } diff --git a/runtime/kusama/src/weights/pallet_balances_nis_counterpart_balances.rs b/runtime/kusama/src/weights/pallet_balances_nis_counterpart_balances.rs new file mode 100644 index 000000000000..ec107400da19 --- /dev/null +++ b/runtime/kusama/src/weights/pallet_balances_nis_counterpart_balances.rs @@ -0,0 +1,105 @@ +// Copyright 2017-2022 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_balances` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot +// benchmark +// pallet +// --chain=kusama-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_balances +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_balances`. +pub struct WeightInfo(PhantomData); +impl pallet_balances::WeightInfo for WeightInfo { + // Storage: NisCounterpartBalances Account (r:2 w:2) + // Storage: System Account (r:1 w:1) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + fn transfer() -> Weight { + // Minimum execution time: 44_076 nanoseconds. + Weight::from_ref_time(44_954_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + // Storage: NisCounterpartBalances Account (r:2 w:2) + // Storage: System Account (r:1 w:1) + fn transfer_keep_alive() -> Weight { + // Minimum execution time: 31_397 nanoseconds. + Weight::from_ref_time(31_869_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + // Storage: NisCounterpartBalances Account (r:1 w:1) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + fn set_balance_creating() -> Weight { + // Minimum execution time: 21_658 nanoseconds. + Weight::from_ref_time(22_126_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: NisCounterpartBalances Account (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + fn set_balance_killing() -> Weight { + // Minimum execution time: 29_939 nanoseconds. + Weight::from_ref_time(31_169_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + // Storage: NisCounterpartBalances Account (r:2 w:2) + // Storage: System Account (r:2 w:2) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + fn force_transfer() -> Weight { + // Minimum execution time: 44_171 nanoseconds. + Weight::from_ref_time(44_796_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } + // Storage: NisCounterpartBalances Account (r:2 w:2) + // Storage: System Account (r:1 w:1) + fn transfer_all() -> Weight { + // Minimum execution time: 39_905 nanoseconds. + Weight::from_ref_time(41_216_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + // Storage: NisCounterpartBalances Account (r:1 w:1) + fn force_unreserve() -> Weight { + // Minimum execution time: 20_700 nanoseconds. + Weight::from_ref_time(20_942_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/runtime/kusama/src/weights/pallet_bounties.rs b/runtime/kusama/src/weights/pallet_bounties.rs index 1a4e849fc9a5..4e4080fa9663 100644 --- a/runtime/kusama/src/weights/pallet_bounties.rs +++ b/runtime/kusama/src/weights/pallet_bounties.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_bounties` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -50,101 +50,101 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Storage: Bounties Bounties (r:0 w:1) /// The range of component `d` is `[0, 16384]`. fn propose_bounty(d: u32, ) -> Weight { - // Minimum execution time: 27_271 nanoseconds. - Weight::from_ref_time(28_531_233 as u64) - // Standard Error: 5 - .saturating_add(Weight::from_ref_time(826 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 29_781 nanoseconds. + Weight::from_ref_time(31_180_609) + // Standard Error: 12 + .saturating_add(Weight::from_ref_time(798).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) // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - // Minimum execution time: 11_154 nanoseconds. - Weight::from_ref_time(11_491_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 12_154 nanoseconds. + Weight::from_ref_time(12_331_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - // Minimum execution time: 10_607 nanoseconds. - Weight::from_ref_time(10_991_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_691 nanoseconds. + Weight::from_ref_time(11_845_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - // Minimum execution time: 37_916 nanoseconds. - Weight::from_ref_time(38_882_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 41_489 nanoseconds. + Weight::from_ref_time(41_816_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - // Minimum execution time: 26_984 nanoseconds. - Weight::from_ref_time(27_792_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 29_192 nanoseconds. + Weight::from_ref_time(29_842_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: ChildBounties ParentChildBounties (r:1 w:0) fn award_bounty() -> Weight { - // Minimum execution time: 22_831 nanoseconds. - Weight::from_ref_time(23_228_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 25_494 nanoseconds. + Weight::from_ref_time(25_846_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: System Account (r:3 w:3) // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - // Minimum execution time: 64_649 nanoseconds. - Weight::from_ref_time(65_727_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 69_638 nanoseconds. + Weight::from_ref_time(70_275_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: ChildBounties ParentChildBounties (r:1 w:0) // Storage: System Account (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - // Minimum execution time: 41_426 nanoseconds. - Weight::from_ref_time(41_831_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 44_759 nanoseconds. + Weight::from_ref_time(45_192_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Bounties Bounties (r:1 w:1) // Storage: ChildBounties ParentChildBounties (r:1 w:0) // Storage: System Account (r:2 w:2) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - // Minimum execution time: 50_735 nanoseconds. - Weight::from_ref_time(51_454_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 53_766 nanoseconds. + Weight::from_ref_time(54_825_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - // Minimum execution time: 20_006 nanoseconds. - Weight::from_ref_time(20_537_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 21_362 nanoseconds. + Weight::from_ref_time(21_892_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Bounties BountyApprovals (r:1 w:1) // Storage: Bounties Bounties (r:2 w:2) // Storage: System Account (r:4 w:4) /// The range of component `b` is `[0, 100]`. fn spend_funds(b: u32, ) -> Weight { - // Minimum execution time: 6_675 nanoseconds. - Weight::from_ref_time(8_384_780 as u64) - // Standard Error: 24_756 - .saturating_add(Weight::from_ref_time(24_193_834 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(b as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(b as u64))) + // Minimum execution time: 7_165 nanoseconds. + Weight::from_ref_time(8_511_058) + // Standard Error: 26_862 + .saturating_add(Weight::from_ref_time(25_766_730).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()))) } } diff --git a/runtime/kusama/src/weights/pallet_child_bounties.rs b/runtime/kusama/src/weights/pallet_child_bounties.rs index 2b191a5fef6b..e9c924c95f6e 100644 --- a/runtime/kusama/src/weights/pallet_child_bounties.rs +++ b/runtime/kusama/src/weights/pallet_child_bounties.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_child_bounties` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -52,57 +52,57 @@ impl pallet_child_bounties::WeightInfo for WeightInfo Weight { - // Minimum execution time: 50_962 nanoseconds. - Weight::from_ref_time(52_811_248 as u64) - // Standard Error: 13 - .saturating_add(Weight::from_ref_time(762 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 53_325 nanoseconds. + Weight::from_ref_time(54_134_414) + // Standard Error: 11 + .saturating_add(Weight::from_ref_time(798).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) // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) fn propose_curator() -> Weight { - // Minimum execution time: 18_238 nanoseconds. - Weight::from_ref_time(18_635_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 19_505 nanoseconds. + Weight::from_ref_time(19_762_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Bounties Bounties (r:1 w:0) // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - // Minimum execution time: 32_611 nanoseconds. - Weight::from_ref_time(33_181_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 34_485 nanoseconds. + Weight::from_ref_time(34_897_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: Bounties Bounties (r:1 w:0) // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - // Minimum execution time: 44_073 nanoseconds. - Weight::from_ref_time(44_577_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 46_969 nanoseconds. + Weight::from_ref_time(47_597_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Bounties Bounties (r:1 w:0) // Storage: ChildBounties ChildBounties (r:1 w:1) fn award_child_bounty() -> Weight { - // Minimum execution time: 27_800 nanoseconds. - Weight::from_ref_time(28_099_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 28_930 nanoseconds. + Weight::from_ref_time(29_187_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ChildBounties ChildBounties (r:1 w:1) // Storage: System Account (r:3 w:3) // Storage: ChildBounties ParentChildBounties (r:1 w:1) // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn claim_child_bounty() -> Weight { - // Minimum execution time: 65_470 nanoseconds. - Weight::from_ref_time(67_848_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 68_827 nanoseconds. + Weight::from_ref_time(69_320_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Bounties Bounties (r:1 w:0) // Storage: ChildBounties ChildBounties (r:1 w:1) @@ -111,10 +111,10 @@ impl pallet_child_bounties::WeightInfo for WeightInfo Weight { - // Minimum execution time: 52_072 nanoseconds. - Weight::from_ref_time(52_649_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 54_410 nanoseconds. + Weight::from_ref_time(54_957_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Bounties Bounties (r:1 w:0) // Storage: ChildBounties ChildBounties (r:1 w:1) @@ -123,9 +123,9 @@ impl pallet_child_bounties::WeightInfo for WeightInfo Weight { - // Minimum execution time: 61_516 nanoseconds. - Weight::from_ref_time(62_160_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 64_477 nanoseconds. + Weight::from_ref_time(65_243_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(7)) } } diff --git a/runtime/kusama/src/weights/pallet_collective_council.rs b/runtime/kusama/src/weights/pallet_collective_council.rs index 2b867ffce399..fc3f6a6c5c41 100644 --- a/runtime/kusama/src/weights/pallet_collective_council.rs +++ b/runtime/kusama/src/weights/pallet_collective_council.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -55,80 +55,80 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 16_031 nanoseconds. - Weight::from_ref_time(16_157_000 as u64) - // Standard Error: 48_159 - .saturating_add(Weight::from_ref_time(5_423_008 as u64).saturating_mul(m as u64)) - // Standard Error: 48_159 - .saturating_add(Weight::from_ref_time(7_456_856 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 17_159 nanoseconds. + Weight::from_ref_time(17_386_000) + // Standard Error: 49_098 + .saturating_add(Weight::from_ref_time(5_640_501).saturating_mul(m.into())) + // Standard Error: 49_098 + .saturating_add(Weight::from_ref_time(7_763_341).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } // Storage: Council Members (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 19_309 nanoseconds. - Weight::from_ref_time(18_691_751 as u64) - // Standard Error: 24 - .saturating_add(Weight::from_ref_time(1_683 as u64).saturating_mul(b as u64)) - // Standard Error: 255 - .saturating_add(Weight::from_ref_time(15_820 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 20_828 nanoseconds. + Weight::from_ref_time(20_148_690) + // Standard Error: 21 + .saturating_add(Weight::from_ref_time(1_937).saturating_mul(b.into())) + // Standard Error: 223 + .saturating_add(Weight::from_ref_time(15_871).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 21_473 nanoseconds. - Weight::from_ref_time(20_706_971 as u64) - // Standard Error: 28 - .saturating_add(Weight::from_ref_time(1_622 as u64).saturating_mul(b as u64)) - // Standard Error: 297 - .saturating_add(Weight::from_ref_time(22_480 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) + // Minimum execution time: 23_137 nanoseconds. + Weight::from_ref_time(22_611_074) + // Standard Error: 41 + .saturating_add(Weight::from_ref_time(1_586).saturating_mul(b.into())) + // Standard Error: 422 + .saturating_add(Weight::from_ref_time(20_879).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalCount (r:1 w:1) // Storage: Council Voting (r:0 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 26_708 nanoseconds. - Weight::from_ref_time(27_050_120 as u64) - // Standard Error: 70 - .saturating_add(Weight::from_ref_time(3_338 as u64).saturating_mul(b as u64)) - // Standard Error: 737 - .saturating_add(Weight::from_ref_time(20_326 as u64).saturating_mul(m as u64)) - // Standard Error: 727 - .saturating_add(Weight::from_ref_time(106_723 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 28_891 nanoseconds. + Weight::from_ref_time(30_004_891) + // Standard Error: 67 + .saturating_add(Weight::from_ref_time(2_998).saturating_mul(b.into())) + // Standard Error: 700 + .saturating_add(Weight::from_ref_time(20_671).saturating_mul(m.into())) + // Standard Error: 691 + .saturating_add(Weight::from_ref_time(110_436).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Council Members (r:1 w:0) // Storage: Council Voting (r:1 w:1) /// The range of component `m` is `[5, 100]`. /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { - // Minimum execution time: 26_639 nanoseconds. - Weight::from_ref_time(27_611_311 as u64) - // Standard Error: 380 - .saturating_add(Weight::from_ref_time(35_933 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_587 nanoseconds. + Weight::from_ref_time(30_985_593) + // Standard Error: 523 + .saturating_add(Weight::from_ref_time(37_334).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) @@ -139,36 +139,36 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 29_178 nanoseconds. - Weight::from_ref_time(31_739_247 as u64) - // Standard Error: 557 - .saturating_add(Weight::from_ref_time(21_928 as u64).saturating_mul(m as u64)) - // Standard Error: 543 - .saturating_add(Weight::from_ref_time(83_446 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 31_318 nanoseconds. + Weight::from_ref_time(33_600_470) + // Standard Error: 533 + .saturating_add(Weight::from_ref_time(19_935).saturating_mul(m.into())) + // Standard Error: 520 + .saturating_add(Weight::from_ref_time(94_658).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 39_173 nanoseconds. - Weight::from_ref_time(40_382_726 as u64) - // Standard Error: 58 - .saturating_add(Weight::from_ref_time(1_584 as u64).saturating_mul(b as u64)) - // Standard Error: 623 - .saturating_add(Weight::from_ref_time(24_345 as u64).saturating_mul(m as u64)) - // Standard Error: 607 - .saturating_add(Weight::from_ref_time(97_786 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 41_518 nanoseconds. + Weight::from_ref_time(42_821_909) + // Standard Error: 59 + .saturating_add(Weight::from_ref_time(2_119).saturating_mul(b.into())) + // Standard Error: 633 + .saturating_add(Weight::from_ref_time(13_816).saturating_mul(m.into())) + // Standard Error: 617 + .saturating_add(Weight::from_ref_time(112_098).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) @@ -180,37 +180,37 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { - // Minimum execution time: 32_457 nanoseconds. - Weight::from_ref_time(33_681_509 as u64) - // Standard Error: 502 - .saturating_add(Weight::from_ref_time(26_118 as u64).saturating_mul(m as u64)) - // Standard Error: 489 - .saturating_add(Weight::from_ref_time(82_917 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 34_513 nanoseconds. + Weight::from_ref_time(35_905_696) + // Standard Error: 471 + .saturating_add(Weight::from_ref_time(24_727).saturating_mul(m.into())) + // Standard Error: 459 + .saturating_add(Weight::from_ref_time(91_432).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) // Storage: Council Prime (r:1 w:0) // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 41_311 nanoseconds. - Weight::from_ref_time(42_427_105 as u64) - // Standard Error: 62 - .saturating_add(Weight::from_ref_time(1_552 as u64).saturating_mul(b as u64)) - // Standard Error: 661 - .saturating_add(Weight::from_ref_time(25_634 as u64).saturating_mul(m as u64)) - // Standard Error: 644 - .saturating_add(Weight::from_ref_time(100_022 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 43_857 nanoseconds. + Weight::from_ref_time(45_661_143) + // Standard Error: 64 + .saturating_add(Weight::from_ref_time(1_977).saturating_mul(b.into())) + // Standard Error: 681 + .saturating_add(Weight::from_ref_time(12_502).saturating_mul(m.into())) + // Standard Error: 664 + .saturating_add(Weight::from_ref_time(109_743).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Proposals (r:1 w:1) // Storage: Council Voting (r:0 w:1) @@ -218,11 +218,11 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `p` is `[1, 100]`. /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { - // Minimum execution time: 18_211 nanoseconds. - Weight::from_ref_time(21_526_337 as u64) - // Standard Error: 690 - .saturating_add(Weight::from_ref_time(94_777 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 19_830 nanoseconds. + Weight::from_ref_time(23_098_905) + // Standard Error: 701 + .saturating_add(Weight::from_ref_time(98_442).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/kusama/src/weights/pallet_collective_technical_committee.rs b/runtime/kusama/src/weights/pallet_collective_technical_committee.rs index 2205878f32a7..68b5e7b7bab9 100644 --- a/runtime/kusama/src/weights/pallet_collective_technical_committee.rs +++ b/runtime/kusama/src/weights/pallet_collective_technical_committee.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -55,80 +55,80 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 16_692 nanoseconds. - Weight::from_ref_time(16_827_000 as u64) - // Standard Error: 47_952 - .saturating_add(Weight::from_ref_time(5_446_193 as u64).saturating_mul(m as u64)) - // Standard Error: 47_952 - .saturating_add(Weight::from_ref_time(7_583_650 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 17_846 nanoseconds. + Weight::from_ref_time(18_153_000) + // Standard Error: 47_680 + .saturating_add(Weight::from_ref_time(5_417_868).saturating_mul(m.into())) + // Standard Error: 47_680 + .saturating_add(Weight::from_ref_time(7_677_098).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } // Storage: TechnicalCommittee Members (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 19_628 nanoseconds. - Weight::from_ref_time(18_949_624 as u64) - // Standard Error: 18 - .saturating_add(Weight::from_ref_time(1_709 as u64).saturating_mul(b as u64)) - // Standard Error: 186 - .saturating_add(Weight::from_ref_time(15_119 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 21_224 nanoseconds. + Weight::from_ref_time(20_521_105) + // Standard Error: 19 + .saturating_add(Weight::from_ref_time(1_899).saturating_mul(b.into())) + // Standard Error: 204 + .saturating_add(Weight::from_ref_time(14_375).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 22_068 nanoseconds. - Weight::from_ref_time(21_218_874 as u64) - // Standard Error: 25 - .saturating_add(Weight::from_ref_time(1_678 as u64).saturating_mul(b as u64)) - // Standard Error: 258 - .saturating_add(Weight::from_ref_time(19_871 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) + // Minimum execution time: 23_738 nanoseconds. + Weight::from_ref_time(22_950_740) + // Standard Error: 34 + .saturating_add(Weight::from_ref_time(1_670).saturating_mul(b.into())) + // Standard Error: 357 + .saturating_add(Weight::from_ref_time(19_075).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) } // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:1) // Storage: TechnicalCommittee ProposalCount (r:1 w:1) // Storage: TechnicalCommittee Voting (r:0 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 27_450 nanoseconds. - Weight::from_ref_time(28_212_498 as u64) - // Standard Error: 65 - .saturating_add(Weight::from_ref_time(3_512 as u64).saturating_mul(b as u64)) - // Standard Error: 686 - .saturating_add(Weight::from_ref_time(17_294 as u64).saturating_mul(m as u64)) - // Standard Error: 678 - .saturating_add(Weight::from_ref_time(111_953 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 29_421 nanoseconds. + Weight::from_ref_time(30_696_255) + // Standard Error: 64 + .saturating_add(Weight::from_ref_time(3_400).saturating_mul(b.into())) + // Standard Error: 670 + .saturating_add(Weight::from_ref_time(19_149).saturating_mul(m.into())) + // Standard Error: 662 + .saturating_add(Weight::from_ref_time(119_172).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee Voting (r:1 w:1) /// The range of component `m` is `[5, 100]`. /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { - // Minimum execution time: 27_739 nanoseconds. - Weight::from_ref_time(29_171_519 as u64) - // Standard Error: 442 - .saturating_add(Weight::from_ref_time(36_814 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 30_393 nanoseconds. + Weight::from_ref_time(31_647_861) + // Standard Error: 485 + .saturating_add(Weight::from_ref_time(38_473).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) @@ -139,36 +139,36 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 31_027 nanoseconds. - Weight::from_ref_time(32_482_964 as u64) - // Standard Error: 447 - .saturating_add(Weight::from_ref_time(22_380 as u64).saturating_mul(m as u64)) - // Standard Error: 436 - .saturating_add(Weight::from_ref_time(81_863 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 33_038 nanoseconds. + Weight::from_ref_time(34_364_089) + // Standard Error: 481 + .saturating_add(Weight::from_ref_time(20_649).saturating_mul(m.into())) + // Standard Error: 469 + .saturating_add(Weight::from_ref_time(95_367).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 40_591 nanoseconds. - Weight::from_ref_time(40_989_302 as u64) - // Standard Error: 56 - .saturating_add(Weight::from_ref_time(1_669 as u64).saturating_mul(b as u64)) - // Standard Error: 593 - .saturating_add(Weight::from_ref_time(25_242 as u64).saturating_mul(m as u64)) - // Standard Error: 578 - .saturating_add(Weight::from_ref_time(98_234 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 42_518 nanoseconds. + Weight::from_ref_time(43_502_130) + // Standard Error: 62 + .saturating_add(Weight::from_ref_time(2_096).saturating_mul(b.into())) + // Standard Error: 656 + .saturating_add(Weight::from_ref_time(14_832).saturating_mul(m.into())) + // Standard Error: 639 + .saturating_add(Weight::from_ref_time(113_147).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) @@ -180,37 +180,37 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { - // Minimum execution time: 33_392 nanoseconds. - Weight::from_ref_time(34_332_427 as u64) - // Standard Error: 455 - .saturating_add(Weight::from_ref_time(27_395 as u64).saturating_mul(m as u64)) - // Standard Error: 443 - .saturating_add(Weight::from_ref_time(81_538 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 35_037 nanoseconds. + Weight::from_ref_time(36_654_786) + // Standard Error: 482 + .saturating_add(Weight::from_ref_time(24_626).saturating_mul(m.into())) + // Standard Error: 470 + .saturating_add(Weight::from_ref_time(93_701).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee Prime (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 42_095 nanoseconds. - Weight::from_ref_time(42_979_139 as u64) - // Standard Error: 57 - .saturating_add(Weight::from_ref_time(1_593 as u64).saturating_mul(b as u64)) - // Standard Error: 607 - .saturating_add(Weight::from_ref_time(25_966 as u64).saturating_mul(m as u64)) - // Standard Error: 591 - .saturating_add(Weight::from_ref_time(100_252 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 44_759 nanoseconds. + Weight::from_ref_time(45_961_421) + // Standard Error: 58 + .saturating_add(Weight::from_ref_time(2_001).saturating_mul(b.into())) + // Standard Error: 613 + .saturating_add(Weight::from_ref_time(15_534).saturating_mul(m.into())) + // Standard Error: 597 + .saturating_add(Weight::from_ref_time(111_237).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Proposals (r:1 w:1) // Storage: TechnicalCommittee Voting (r:0 w:1) @@ -218,11 +218,11 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `p` is `[1, 100]`. /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { - // Minimum execution time: 18_749 nanoseconds. - Weight::from_ref_time(22_120_550 as u64) - // Standard Error: 692 - .saturating_add(Weight::from_ref_time(95_583 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 20_592 nanoseconds. + Weight::from_ref_time(23_613_847) + // Standard Error: 651 + .saturating_add(Weight::from_ref_time(100_049).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/kusama/src/weights/pallet_conviction_voting.rs b/runtime/kusama/src/weights/pallet_conviction_voting.rs index d5e1568efb20..9bcb1438ae2b 100644 --- a/runtime/kusama/src/weights/pallet_conviction_voting.rs +++ b/runtime/kusama/src/weights/pallet_conviction_voting.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_conviction_voting` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -50,10 +50,10 @@ impl pallet_conviction_voting::WeightInfo for WeightInf // Storage: Balances Locks (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn vote_new() -> Weight { - // Minimum execution time: 125_577 nanoseconds. - Weight::from_ref_time(128_422_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 133_968 nanoseconds. + Weight::from_ref_time(138_131_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: ConvictionVoting VotingFor (r:1 w:1) @@ -61,27 +61,27 @@ impl pallet_conviction_voting::WeightInfo for WeightInf // Storage: Balances Locks (r:1 w:1) // Storage: Scheduler Agenda (r:2 w:2) fn vote_existing() -> Weight { - // Minimum execution time: 153_040 nanoseconds. - Weight::from_ref_time(155_995_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 157_963 nanoseconds. + Weight::from_ref_time(161_930_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: ConvictionVoting VotingFor (r:1 w:1) // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:2 w:2) fn remove_vote() -> Weight { - // Minimum execution time: 130_240 nanoseconds. - Weight::from_ref_time(133_249_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 137_724 nanoseconds. + Weight::from_ref_time(139_037_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: ConvictionVoting VotingFor (r:1 w:1) // Storage: Referenda ReferendumInfoFor (r:1 w:0) fn remove_other_vote() -> Weight { - // Minimum execution time: 70_042 nanoseconds. - Weight::from_ref_time(72_074_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 76_846 nanoseconds. + Weight::from_ref_time(78_498_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ConvictionVoting VotingFor (r:2 w:2) // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) @@ -90,36 +90,36 @@ impl pallet_conviction_voting::WeightInfo for WeightInf // Storage: Scheduler Agenda (r:2 w:2) /// The range of component `r` is `[0, 512]`. fn delegate(r: u32, ) -> Weight { - // Minimum execution time: 76_733 nanoseconds. - Weight::from_ref_time(707_216_284 as u64) - // Standard Error: 60_799 - .saturating_add(Weight::from_ref_time(28_505_942 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(6 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64))) + // Minimum execution time: 77_270 nanoseconds. + Weight::from_ref_time(723_885_274) + // Standard Error: 60_058 + .saturating_add(Weight::from_ref_time(27_101_815).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .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((1_u64).saturating_mul(r.into()))) } // Storage: ConvictionVoting VotingFor (r:2 w:2) // Storage: Referenda ReferendumInfoFor (r:10 w:10) // Storage: Scheduler Agenda (r:2 w:2) /// The range of component `r` is `[0, 512]`. fn undelegate(r: u32, ) -> Weight { - // Minimum execution time: 52_748 nanoseconds. - Weight::from_ref_time(683_979_746 as u64) - // Standard Error: 61_513 - .saturating_add(Weight::from_ref_time(28_523_157 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64))) + // Minimum execution time: 56_587 nanoseconds. + Weight::from_ref_time(697_756_743) + // Standard Error: 60_091 + .saturating_add(Weight::from_ref_time(27_152_327).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((1_u64).saturating_mul(r.into()))) } // Storage: ConvictionVoting VotingFor (r:1 w:1) // Storage: ConvictionVoting ClassLocksFor (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn unlock() -> Weight { - // Minimum execution time: 87_809 nanoseconds. - Weight::from_ref_time(90_514_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 94_375 nanoseconds. + Weight::from_ref_time(96_800_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/kusama/src/weights/pallet_democracy.rs b/runtime/kusama/src/weights/pallet_democracy.rs index 9ed911379aff..384f20001d13 100644 --- a/runtime/kusama/src/weights/pallet_democracy.rs +++ b/runtime/kusama/src/weights/pallet_democracy.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_democracy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -49,43 +49,43 @@ impl pallet_democracy::WeightInfo for WeightInfo { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - // Minimum execution time: 41_759 nanoseconds. - Weight::from_ref_time(42_405_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 43_332 nanoseconds. + Weight::from_ref_time(44_449_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy DepositOf (r:1 w:1) fn second() -> Weight { - // Minimum execution time: 38_699 nanoseconds. - Weight::from_ref_time(39_568_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 40_024 nanoseconds. + Weight::from_ref_time(42_081_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new() -> Weight { - // Minimum execution time: 48_618 nanoseconds. - Weight::from_ref_time(49_513_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 51_246 nanoseconds. + Weight::from_ref_time(51_986_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing() -> Weight { - // Minimum execution time: 48_709 nanoseconds. - Weight::from_ref_time(49_737_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 51_221 nanoseconds. + Weight::from_ref_time(52_200_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - // Minimum execution time: 20_352 nanoseconds. - Weight::from_ref_time(20_676_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 22_015 nanoseconds. + Weight::from_ref_time(22_272_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy PublicProps (r:1 w:1) // Storage: Democracy DepositOf (r:1 w:1) @@ -94,75 +94,75 @@ impl pallet_democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Blacklist (r:0 w:1) fn blacklist() -> Weight { - // Minimum execution time: 75_042 nanoseconds. - Weight::from_ref_time(76_607_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 79_080 nanoseconds. + Weight::from_ref_time(79_914_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose() -> Weight { - // Minimum execution time: 15_470 nanoseconds. - Weight::from_ref_time(16_352_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 16_980 nanoseconds. + Weight::from_ref_time(17_479_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - // Minimum execution time: 4_297 nanoseconds. - Weight::from_ref_time(4_450_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_733 nanoseconds. + Weight::from_ref_time(4_876_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - // Minimum execution time: 4_074 nanoseconds. - Weight::from_ref_time(4_261_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_601 nanoseconds. + Weight::from_ref_time(4_717_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - // Minimum execution time: 20_016 nanoseconds. - Weight::from_ref_time(20_413_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 21_450 nanoseconds. + Weight::from_ref_time(21_767_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external() -> Weight { - // Minimum execution time: 24_906 nanoseconds. - Weight::from_ref_time(25_500_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 26_708 nanoseconds. + Weight::from_ref_time(27_394_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy PublicProps (r:1 w:1) // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn cancel_proposal() -> Weight { - // Minimum execution time: 63_398 nanoseconds. - Weight::from_ref_time(64_382_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 67_036 nanoseconds. + Weight::from_ref_time(68_231_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - // Minimum execution time: 12_688 nanoseconds. - Weight::from_ref_time(13_056_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 13_672 nanoseconds. + Weight::from_ref_time(14_014_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:2 w:0) /// The range of component `r` is `[0, 99]`. fn on_initialize_base(r: u32, ) -> Weight { - // Minimum execution time: 5_838 nanoseconds. - Weight::from_ref_time(9_062_912 as u64) - // Standard Error: 3_860 - .saturating_add(Weight::from_ref_time(2_072_063 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 6_105 nanoseconds. + Weight::from_ref_time(9_273_381) + // Standard Error: 3_886 + .saturating_add(Weight::from_ref_time(2_093_384).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) @@ -172,91 +172,91 @@ impl pallet_democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumInfoOf (r:2 w:0) /// The range of component `r` is `[0, 99]`. fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - // Minimum execution time: 8_322 nanoseconds. - Weight::from_ref_time(11_779_246 as u64) - // Standard Error: 4_107 - .saturating_add(Weight::from_ref_time(2_078_653 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_492 nanoseconds. + Weight::from_ref_time(12_036_123) + // Standard Error: 3_615 + .saturating_add(Weight::from_ref_time(2_085_813).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy VotingOf (r:3 w:3) // Storage: Balances Locks (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:2 w:2) /// The range of component `r` is `[0, 99]`. fn delegate(r: u32, ) -> Weight { - // Minimum execution time: 40_236 nanoseconds. - Weight::from_ref_time(47_071_432 as u64) - // Standard Error: 5_329 - .saturating_add(Weight::from_ref_time(2_956_656 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64))) + // Minimum execution time: 43_017 nanoseconds. + Weight::from_ref_time(49_545_735) + // Standard Error: 5_877 + .saturating_add(Weight::from_ref_time(3_070_283).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((1_u64).saturating_mul(r.into()))) } // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:2 w:2) /// The range of component `r` is `[0, 99]`. fn undelegate(r: u32, ) -> Weight { - // Minimum execution time: 23_757 nanoseconds. - Weight::from_ref_time(27_469_795 as u64) - // Standard Error: 4_678 - .saturating_add(Weight::from_ref_time(2_979_545 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64))) + // Minimum execution time: 25_997 nanoseconds. + Weight::from_ref_time(28_582_986) + // Standard Error: 5_921 + .saturating_add(Weight::from_ref_time(3_063_954).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - // Minimum execution time: 4_993 nanoseconds. - Weight::from_ref_time(5_073_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_244 nanoseconds. + Weight::from_ref_time(5_386_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) /// The range of component `r` is `[0, 99]`. fn unlock_remove(r: u32, ) -> Weight { - // Minimum execution time: 23_394 nanoseconds. - Weight::from_ref_time(30_461_547 as u64) - // Standard Error: 1_584 - .saturating_add(Weight::from_ref_time(32_550 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 25_877 nanoseconds. + Weight::from_ref_time(32_903_261) + // Standard Error: 1_579 + .saturating_add(Weight::from_ref_time(31_424).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) /// The range of component `r` is `[0, 99]`. fn unlock_set(r: u32, ) -> Weight { - // Minimum execution time: 28_280 nanoseconds. - Weight::from_ref_time(30_149_111 as u64) - // Standard Error: 726 - .saturating_add(Weight::from_ref_time(67_624 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 30_681 nanoseconds. + Weight::from_ref_time(32_498_252) + // Standard Error: 1_239 + .saturating_add(Weight::from_ref_time(68_223).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) /// The range of component `r` is `[1, 100]`. fn remove_vote(r: u32, ) -> Weight { - // Minimum execution time: 15_288 nanoseconds. - Weight::from_ref_time(17_863_090 as u64) - // Standard Error: 824 - .saturating_add(Weight::from_ref_time(69_037 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 16_955 nanoseconds. + Weight::from_ref_time(19_294_735) + // Standard Error: 841 + .saturating_add(Weight::from_ref_time(66_746).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) /// The range of component `r` is `[1, 100]`. fn remove_other_vote(r: u32, ) -> Weight { - // Minimum execution time: 15_235 nanoseconds. - Weight::from_ref_time(17_900_284 as u64) - // Standard Error: 847 - .saturating_add(Weight::from_ref_time(68_753 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 16_564 nanoseconds. + Weight::from_ref_time(19_243_442) + // Standard Error: 957 + .saturating_add(Weight::from_ref_time(69_793).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/kusama/src/weights/pallet_election_provider_multi_phase.rs b/runtime/kusama/src/weights/pallet_election_provider_multi_phase.rs index 1b6c20565fe0..7922051c6b8b 100644 --- a/runtime/kusama/src/weights/pallet_election_provider_multi_phase.rs +++ b/runtime/kusama/src/weights/pallet_election_provider_multi_phase.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_election_provider_multi_phase` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -53,52 +53,54 @@ impl pallet_election_provider_multi_phase::WeightInfo f // Storage: Staking ForceEra (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) fn on_initialize_nothing() -> Weight { - // Minimum execution time: 15_107 nanoseconds. - Weight::from_ref_time(15_366_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) + // Minimum execution time: 16_970 nanoseconds. + Weight::from_ref_time(17_363_000) + .saturating_add(T::DbWeight::get().reads(8)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_signed() -> Weight { - // Minimum execution time: 14_010 nanoseconds. - Weight::from_ref_time(14_784_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 14_655 nanoseconds. + Weight::from_ref_time(14_881_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_unsigned() -> Weight { - // Minimum execution time: 13_853 nanoseconds. - Weight::from_ref_time(14_445_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 14_451 nanoseconds. + Weight::from_ref_time(14_825_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) // Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) fn finalize_signed_phase_accept_solution() -> Weight { - // Minimum execution time: 28_285 nanoseconds. - Weight::from_ref_time(28_639_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 29_693 nanoseconds. + Weight::from_ref_time(30_030_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: System Account (r:1 w:1) fn finalize_signed_phase_reject_solution() -> Weight { - // Minimum execution time: 22_109 nanoseconds. - Weight::from_ref_time(22_587_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 23_101 nanoseconds. + Weight::from_ref_time(23_294_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ElectionProviderMultiPhase SnapshotMetadata (r:0 w:1) // Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) // Storage: ElectionProviderMultiPhase Snapshot (r:0 w:1) /// 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 { - // Minimum execution time: 622_518 nanoseconds. - Weight::from_ref_time(647_402_000 as u64) - // Standard Error: 4_839 - .saturating_add(Weight::from_ref_time(375_965 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + fn create_snapshot_internal(v: u32, t: u32, ) -> Weight { + // Minimum execution time: 632_291 nanoseconds. + Weight::from_ref_time(32_358_301) + // Standard Error: 2_306 + .saturating_add(Weight::from_ref_time(547_479).saturating_mul(v.into())) + // Standard Error: 4_610 + .saturating_add(Weight::from_ref_time(80_995).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) @@ -113,12 +115,12 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn elect_queued(a: u32, _d: u32, ) -> Weight { - // Minimum execution time: 369_213 nanoseconds. - Weight::from_ref_time(373_298_000 as u64) - // Standard Error: 8_881 - .saturating_add(Weight::from_ref_time(578_551 as u64).saturating_mul(a as u64)) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 371_762 nanoseconds. + Weight::from_ref_time(380_412_000) + // Standard Error: 8_912 + .saturating_add(Weight::from_ref_time(590_949).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(9)) } // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) @@ -127,10 +129,10 @@ impl pallet_election_provider_multi_phase::WeightInfo f // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) fn submit() -> Weight { - // Minimum execution time: 50_173 nanoseconds. - Weight::from_ref_time(51_434_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 51_620 nanoseconds. + Weight::from_ref_time(51_944_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: ElectionProviderMultiPhase Round (r:1 w:0) @@ -144,12 +146,12 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn submit_unsigned(_v: u32, _t: u32, a: u32, _d: u32, ) -> Weight { - // Minimum execution time: 6_771_975 nanoseconds. - Weight::from_ref_time(6_832_732_000 as u64) - // Standard Error: 58_044 - .saturating_add(Weight::from_ref_time(6_976_679 as u64).saturating_mul(a as u64)) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 6_963_307 nanoseconds. + Weight::from_ref_time(6_992_705_000) + // Standard Error: 62_150 + .saturating_add(Weight::from_ref_time(7_173_871).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) @@ -160,12 +162,12 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn feasibility_check(v: u32, _t: u32, a: u32, _d: u32, ) -> Weight { - // Minimum execution time: 5_640_118 nanoseconds. - Weight::from_ref_time(5_681_788_000 as u64) - // Standard Error: 18_489 - .saturating_add(Weight::from_ref_time(82_866 as u64).saturating_mul(v as u64)) - // Standard Error: 54_791 - .saturating_add(Weight::from_ref_time(5_418_533 as u64).saturating_mul(a as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) + // Minimum execution time: 5_821_005 nanoseconds. + Weight::from_ref_time(5_889_611_000) + // Standard Error: 24_617 + .saturating_add(Weight::from_ref_time(377_034).saturating_mul(v.into())) + // Standard Error: 72_952 + .saturating_add(Weight::from_ref_time(5_370_344).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(4)) } } diff --git a/runtime/kusama/src/weights/pallet_elections_phragmen.rs b/runtime/kusama/src/weights/pallet_elections_phragmen.rs index 55f4aebda844..f2b2f38789d6 100644 --- a/runtime/kusama/src/weights/pallet_elections_phragmen.rs +++ b/runtime/kusama/src/weights/pallet_elections_phragmen.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_elections_phragmen` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -51,12 +51,12 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Balances Locks (r:1 w:1) /// The range of component `v` is `[1, 16]`. fn vote_equal(v: u32, ) -> Weight { - // Minimum execution time: 31_085 nanoseconds. - Weight::from_ref_time(32_736_954 as u64) - // Standard Error: 3_845 - .saturating_add(Weight::from_ref_time(168_838 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 32_051 nanoseconds. + Weight::from_ref_time(33_997_284) + // Standard Error: 5_326 + .saturating_add(Weight::from_ref_time(152_057).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Candidates (r:1 w:0) // Storage: PhragmenElection Members (r:1 w:0) @@ -65,12 +65,12 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Balances Locks (r:1 w:1) /// The range of component `v` is `[2, 16]`. fn vote_more(v: u32, ) -> Weight { - // Minimum execution time: 41_132 nanoseconds. - Weight::from_ref_time(42_303_475 as u64) - // Standard Error: 5_730 - .saturating_add(Weight::from_ref_time(208_484 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 42_433 nanoseconds. + Weight::from_ref_time(44_061_458) + // Standard Error: 5_255 + .saturating_add(Weight::from_ref_time(175_150).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Candidates (r:1 w:0) // Storage: PhragmenElection Members (r:1 w:0) @@ -79,42 +79,42 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Balances Locks (r:1 w:1) /// The range of component `v` is `[2, 16]`. fn vote_less(v: u32, ) -> Weight { - // Minimum execution time: 41_877 nanoseconds. - Weight::from_ref_time(42_421_665 as u64) - // Standard Error: 4_617 - .saturating_add(Weight::from_ref_time(186_992 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 42_410 nanoseconds. + Weight::from_ref_time(43_612_356) + // Standard Error: 5_057 + .saturating_add(Weight::from_ref_time(206_540).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn remove_voter() -> Weight { - // Minimum execution time: 39_668 nanoseconds. - Weight::from_ref_time(40_061_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 41_764 nanoseconds. + Weight::from_ref_time(42_348_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Candidates (r:1 w:1) // Storage: PhragmenElection Members (r:1 w:0) // Storage: PhragmenElection RunnersUp (r:1 w:0) /// The range of component `c` is `[1, 1000]`. fn submit_candidacy(c: u32, ) -> Weight { - // Minimum execution time: 36_292 nanoseconds. - Weight::from_ref_time(28_441_584 as u64) - // Standard Error: 999 - .saturating_add(Weight::from_ref_time(92_295 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 36_936 nanoseconds. + Weight::from_ref_time(28_854_430) + // Standard Error: 1_036 + .saturating_add(Weight::from_ref_time(92_014).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: PhragmenElection Candidates (r:1 w:1) /// The range of component `c` is `[1, 1000]`. fn renounce_candidacy_candidate(c: u32, ) -> Weight { - // Minimum execution time: 32_157 nanoseconds. - Weight::from_ref_time(23_445_460 as u64) - // Standard Error: 1_039 - .saturating_add(Weight::from_ref_time(73_470 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 32_665 nanoseconds. + Weight::from_ref_time(24_381_480) + // Standard Error: 1_038 + .saturating_add(Weight::from_ref_time(72_251).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: PhragmenElection Members (r:1 w:1) // Storage: PhragmenElection RunnersUp (r:1 w:1) @@ -122,22 +122,22 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn renounce_candidacy_members() -> Weight { - // Minimum execution time: 45_300 nanoseconds. - Weight::from_ref_time(47_067_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 45_774 nanoseconds. + Weight::from_ref_time(47_677_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: PhragmenElection RunnersUp (r:1 w:1) fn renounce_candidacy_runners_up() -> Weight { - // Minimum execution time: 34_427 nanoseconds. - Weight::from_ref_time(35_301_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 35_341 nanoseconds. + Weight::from_ref_time(36_021_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Benchmark Override (r:0 w:0) fn remove_member_without_replacement() -> Weight { // Minimum execution time: 2_000_000_000 nanoseconds. - Weight::from_ref_time(2_000_000_000_000 as u64) + Weight::from_ref_time(2_000_000_000_000) } // Storage: PhragmenElection Members (r:1 w:1) // Storage: System Account (r:1 w:1) @@ -146,10 +146,10 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn remove_member_with_replacement() -> Weight { - // Minimum execution time: 59_116 nanoseconds. - Weight::from_ref_time(60_245_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 59_963 nanoseconds. + Weight::from_ref_time(61_133_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: PhragmenElection Voting (r:5001 w:5000) // Storage: PhragmenElection Members (r:1 w:0) @@ -160,13 +160,13 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn /// The range of component `v` is `[5000, 10000]`. /// The range of component `d` is `[0, 5000]`. fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { - // Minimum execution time: 277_672_844 nanoseconds. - Weight::from_ref_time(278_514_899_000 as u64) - // Standard Error: 241_305 - .saturating_add(Weight::from_ref_time(34_329_964 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(v as u64))) + // Minimum execution time: 286_333_718 nanoseconds. + Weight::from_ref_time(286_839_378_000) + // Standard Error: 247_683 + .saturating_add(Weight::from_ref_time(35_671_313).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) } // Storage: PhragmenElection Candidates (r:1 w:1) // Storage: PhragmenElection Members (r:1 w:1) @@ -181,16 +181,16 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn /// The range of component `v` is `[1, 10000]`. /// The range of component `e` is `[10000, 160000]`. fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { - // Minimum execution time: 28_457_507 nanoseconds. - Weight::from_ref_time(28_618_929_000 as u64) - // Standard Error: 542_445 - .saturating_add(Weight::from_ref_time(45_671_268 as u64).saturating_mul(v as u64)) - // Standard Error: 34_810 - .saturating_add(Weight::from_ref_time(2_339_767 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(265 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().writes(6 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + // Minimum execution time: 29_154_342 nanoseconds. + Weight::from_ref_time(29_360_734_000) + // Standard Error: 541_981 + .saturating_add(Weight::from_ref_time(45_981_042).saturating_mul(v.into())) + // Standard Error: 34_781 + .saturating_add(Weight::from_ref_time(2_353_500).saturating_mul(e.into())) + .saturating_add(T::DbWeight::get().reads(265)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) } } diff --git a/runtime/kusama/src/weights/pallet_fast_unstake.rs b/runtime/kusama/src/weights/pallet_fast_unstake.rs index a79fa732abe0..7704562359e5 100644 --- a/runtime/kusama/src/weights/pallet_fast_unstake.rs +++ b/runtime/kusama/src/weights/pallet_fast_unstake.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_fast_unstake` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -49,56 +49,57 @@ impl pallet_fast_unstake::WeightInfo for WeightInfo // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking SlashingSpans (r:1 w:0) - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Ledger (r:0 w:1) - // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SlashingSpans (r:64 w:0) + // Storage: Staking Bonded (r:64 w:64) + // Storage: Staking Validators (r:64 w:0) + // Storage: Staking Nominators (r:64 w:0) + // Storage: System Account (r:64 w:64) + // Storage: Balances Locks (r:64 w:64) + // Storage: Staking Ledger (r:0 w:64) + // Storage: Staking Payee (r:0 w:64) fn on_idle_unstake() -> Weight { - // Minimum execution time: 70_698 nanoseconds. - Weight::from_ref_time(71_645_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 2_333_815 nanoseconds. + Weight::from_ref_time(2_345_273_000) + .saturating_add(T::DbWeight::get().reads(389)) + .saturating_add(T::DbWeight::get().writes(321)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking ValidatorCount (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) - // Storage: FastUnstake Queue (r:2 w:1) + // Storage: FastUnstake Queue (r:65 w:64) // Storage: FastUnstake CounterForQueue (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking ErasStakers (r:56 w:0) /// The range of component `x` is `[28, 3584]`. fn on_idle_check(x: u32, ) -> Weight { - // Minimum execution time: 425_735 nanoseconds. - Weight::from_ref_time(428_188_000 as u64) - // Standard Error: 19_127 - .saturating_add(Weight::from_ref_time(11_434_878 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(22 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 22_277_324 nanoseconds. + Weight::from_ref_time(22_625_767_000) + // Standard Error: 479_422 + .saturating_add(Weight::from_ref_time(628_500_181).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(85)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(66)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: FastUnstake Queue (r:1 w:1) // Storage: FastUnstake Head (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn register_fast_unstake() -> Weight { - // Minimum execution time: 93_096 nanoseconds. - Weight::from_ref_time(93_867_000 as u64) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 131_140 nanoseconds. + Weight::from_ref_time(133_608_000) + .saturating_add(T::DbWeight::get().reads(15)) + .saturating_add(T::DbWeight::get().writes(10)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) @@ -106,15 +107,15 @@ impl pallet_fast_unstake::WeightInfo for WeightInfo // Storage: FastUnstake Head (r:1 w:0) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn deregister() -> Weight { - // Minimum execution time: 40_468 nanoseconds. - Weight::from_ref_time(41_354_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 52_243 nanoseconds. + Weight::from_ref_time(53_351_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FastUnstake ErasToCheckPerBlock (r:0 w:1) fn control() -> Weight { - // Minimum execution time: 3_682 nanoseconds. - Weight::from_ref_time(3_845_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_267 nanoseconds. + Weight::from_ref_time(4_458_000) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/pallet_gilt.rs b/runtime/kusama/src/weights/pallet_gilt.rs deleted file mode 100644 index ee4c85d4f57a..000000000000 --- a/runtime/kusama/src/weights/pallet_gilt.rs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2017-2022 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_gilt` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 - -// Executed Command: -// ./target/production/polkadot -// benchmark -// pallet -// --chain=kusama-dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_gilt -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/kusama/src/weights/ - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::Weight}; -use sp_std::marker::PhantomData; - -/// Weight functions for `pallet_gilt`. -pub struct WeightInfo(PhantomData); -impl pallet_gilt::WeightInfo for WeightInfo { - // Storage: Gilt Queues (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - /// The range of component `l` is `[0, 999]`. - fn place_bid(l: u32, ) -> Weight { - // Minimum execution time: 35_662 nanoseconds. - Weight::from_ref_time(33_310_341 as u64) - // Standard Error: 699 - .saturating_add(Weight::from_ref_time(70_825 as u64).saturating_mul(l as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Gilt Queues (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - fn place_bid_max() -> Weight { - // Minimum execution time: 98_299 nanoseconds. - Weight::from_ref_time(99_875_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Gilt Queues (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - /// The range of component `l` is `[1, 1000]`. - fn retract_bid(l: u32, ) -> Weight { - // Minimum execution time: 36_914 nanoseconds. - Weight::from_ref_time(33_609_132 as u64) - // Standard Error: 688 - .saturating_add(Weight::from_ref_time(61_346 as u64).saturating_mul(l as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Gilt ActiveTotal (r:1 w:1) - fn set_target() -> Weight { - // Minimum execution time: 6_346 nanoseconds. - Weight::from_ref_time(6_537_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: Gilt Active (r:1 w:1) - // Storage: Gilt ActiveTotal (r:1 w:1) - fn thaw() -> Weight { - // Minimum execution time: 45_145 nanoseconds. - Weight::from_ref_time(45_983_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Gilt ActiveTotal (r:1 w:0) - fn pursue_target_noop() -> Weight { - // Minimum execution time: 2_703 nanoseconds. - Weight::from_ref_time(2_853_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - } - // Storage: Gilt ActiveTotal (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - // Storage: Gilt Queues (r:1 w:1) - // Storage: Gilt Active (r:0 w:20) - /// The range of component `b` is `[0, 1000]`. - fn pursue_target_per_item(b: u32, ) -> Weight { - // Minimum execution time: 27_077 nanoseconds. - Weight::from_ref_time(31_097_279 as u64) - // Standard Error: 2_945 - .saturating_add(Weight::from_ref_time(3_841_676 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(b as u64))) - } - // Storage: Gilt ActiveTotal (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - // Storage: Gilt Queues (r:6 w:6) - // Storage: Gilt Active (r:0 w:6) - /// The range of component `q` is `[0, 300]`. - fn pursue_target_per_queue(q: u32, ) -> Weight { - // Minimum execution time: 27_042 nanoseconds. - Weight::from_ref_time(26_820_692 as u64) - // Standard Error: 6_645 - .saturating_add(Weight::from_ref_time(6_471_496 as u64).saturating_mul(q as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(q as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(q as u64))) - } -} diff --git a/runtime/kusama/src/weights/pallet_identity.rs b/runtime/kusama/src/weights/pallet_identity.rs index f702a223acbf..2a565fb81a3c 100644 --- a/runtime/kusama/src/weights/pallet_identity.rs +++ b/runtime/kusama/src/weights/pallet_identity.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_identity` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -47,52 +47,52 @@ impl pallet_identity::WeightInfo for WeightInfo { // Storage: Identity Registrars (r:1 w:1) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { - // Minimum execution time: 16_040 nanoseconds. - Weight::from_ref_time(17_245_202 as u64) - // Standard Error: 2_979 - .saturating_add(Weight::from_ref_time(153_233 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 17_074 nanoseconds. + Weight::from_ref_time(18_488_690) + // Standard Error: 2_915 + .saturating_add(Weight::from_ref_time(140_389).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) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn set_identity(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 34_388 nanoseconds. - Weight::from_ref_time(33_517_449 as u64) - // Standard Error: 3_495 - .saturating_add(Weight::from_ref_time(114_197 as u64).saturating_mul(r as u64)) - // Standard Error: 682 - .saturating_add(Weight::from_ref_time(304_413 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 36_384 nanoseconds. + Weight::from_ref_time(35_515_499) + // Standard Error: 3_576 + .saturating_add(Weight::from_ref_time(101_933).saturating_mul(r.into())) + // Standard Error: 697 + .saturating_add(Weight::from_ref_time(341_160).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:2 w:2) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { - // Minimum execution time: 9_735 nanoseconds. - Weight::from_ref_time(27_554_907 as u64) - // Standard Error: 4_993 - .saturating_add(Weight::from_ref_time(2_147_723 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 10_422 nanoseconds. + Weight::from_ref_time(29_301_371) + // Standard Error: 5_174 + .saturating_add(Weight::from_ref_time(2_238_423).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()))) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:2) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { - // Minimum execution time: 9_763 nanoseconds. - Weight::from_ref_time(27_412_160 as u64) - // Standard Error: 4_153 - .saturating_add(Weight::from_ref_time(931_626 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 10_547 nanoseconds. + Weight::from_ref_time(29_481_225) + // Standard Error: 4_445 + .saturating_add(Weight::from_ref_time(965_691).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) // Storage: Identity IdentityOf (r:1 w:1) @@ -101,88 +101,88 @@ impl pallet_identity::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. /// The range of component `x` is `[0, 100]`. fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - // Minimum execution time: 50_615 nanoseconds. - Weight::from_ref_time(35_426_490 as u64) - // Standard Error: 5_633 - .saturating_add(Weight::from_ref_time(102_541 as u64).saturating_mul(r as u64)) - // Standard Error: 1_100 - .saturating_add(Weight::from_ref_time(900_269 as u64).saturating_mul(s as u64)) - // Standard Error: 1_100 - .saturating_add(Weight::from_ref_time(162_883 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 52_976 nanoseconds. + Weight::from_ref_time(36_889_254) + // Standard Error: 6_751 + .saturating_add(Weight::from_ref_time(118_432).saturating_mul(r.into())) + // Standard Error: 1_318 + .saturating_add(Weight::from_ref_time(936_998).saturating_mul(s.into())) + // Standard Error: 1_318 + .saturating_add(Weight::from_ref_time(173_470).saturating_mul(x.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) // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn request_judgement(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 36_689 nanoseconds. - Weight::from_ref_time(34_440_440 as u64) - // Standard Error: 4_297 - .saturating_add(Weight::from_ref_time(157_407 as u64).saturating_mul(r as u64)) - // Standard Error: 838 - .saturating_add(Weight::from_ref_time(322_563 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 38_371 nanoseconds. + Weight::from_ref_time(37_795_137) + // Standard Error: 6_070 + .saturating_add(Weight::from_ref_time(102_441).saturating_mul(r.into())) + // Standard Error: 1_184 + .saturating_add(Weight::from_ref_time(356_618).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn cancel_request(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 32_677 nanoseconds. - Weight::from_ref_time(32_904_285 as u64) - // Standard Error: 7_174 - .saturating_add(Weight::from_ref_time(53_862 as u64).saturating_mul(r as u64)) - // Standard Error: 1_399 - .saturating_add(Weight::from_ref_time(326_172 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 34_732 nanoseconds. + Weight::from_ref_time(34_398_160) + // Standard Error: 4_045 + .saturating_add(Weight::from_ref_time(85_223).saturating_mul(r.into())) + // Standard Error: 789 + .saturating_add(Weight::from_ref_time(356_362).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity Registrars (r:1 w:1) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { - // Minimum execution time: 7_883 nanoseconds. - Weight::from_ref_time(9_085_857 as u64) - // Standard Error: 2_860 - .saturating_add(Weight::from_ref_time(116_017 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_878 nanoseconds. + Weight::from_ref_time(9_820_687) + // Standard Error: 2_298 + .saturating_add(Weight::from_ref_time(121_287).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) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { - // Minimum execution time: 8_203 nanoseconds. - Weight::from_ref_time(9_318_119 as u64) - // Standard Error: 2_242 - .saturating_add(Weight::from_ref_time(117_787 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_286 nanoseconds. + Weight::from_ref_time(10_231_571) + // Standard Error: 2_053 + .saturating_add(Weight::from_ref_time(113_611).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) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { - // Minimum execution time: 8_037 nanoseconds. - Weight::from_ref_time(9_045_757 as u64) - // Standard Error: 2_484 - .saturating_add(Weight::from_ref_time(128_923 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_198 nanoseconds. + Weight::from_ref_time(10_003_435) + // Standard Error: 1_729 + .saturating_add(Weight::from_ref_time(119_368).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) // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 19]`. /// The range of component `x` is `[0, 100]`. fn provide_judgement(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 26_988 nanoseconds. - Weight::from_ref_time(27_210_149 as u64) - // Standard Error: 13_954 - .saturating_add(Weight::from_ref_time(60_196 as u64).saturating_mul(r as u64)) - // Standard Error: 2_581 - .saturating_add(Weight::from_ref_time(542_227 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 28_302 nanoseconds. + Weight::from_ref_time(27_949_716) + // Standard Error: 4_917 + .saturating_add(Weight::from_ref_time(111_693).saturating_mul(r.into())) + // Standard Error: 909 + .saturating_add(Weight::from_ref_time(598_410).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity IdentityOf (r:1 w:1) @@ -192,62 +192,62 @@ impl pallet_identity::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. /// The range of component `x` is `[0, 100]`. fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight { - // Minimum execution time: 61_245 nanoseconds. - Weight::from_ref_time(46_208_772 as u64) - // Standard Error: 8_712 - .saturating_add(Weight::from_ref_time(137_988 as u64).saturating_mul(r as u64)) - // Standard Error: 1_701 - .saturating_add(Weight::from_ref_time(901_893 as u64).saturating_mul(s as u64)) - // Standard Error: 1_701 - .saturating_add(Weight::from_ref_time(167_735 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 64_861 nanoseconds. + Weight::from_ref_time(47_985_084) + // Standard Error: 6_854 + .saturating_add(Weight::from_ref_time(133_243).saturating_mul(r.into())) + // Standard Error: 1_338 + .saturating_add(Weight::from_ref_time(949_016).saturating_mul(s.into())) + // Standard Error: 1_338 + .saturating_add(Weight::from_ref_time(173_824).saturating_mul(x.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) // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { - // Minimum execution time: 30_192 nanoseconds. - Weight::from_ref_time(36_327_198 as u64) - // Standard Error: 1_699 - .saturating_add(Weight::from_ref_time(74_349 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 32_615 nanoseconds. + Weight::from_ref_time(38_659_172) + // Standard Error: 1_793 + .saturating_add(Weight::from_ref_time(75_038).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) // Storage: Identity SuperOf (r:1 w:1) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { - // Minimum execution time: 13_068 nanoseconds. - Weight::from_ref_time(15_455_367 as u64) - // Standard Error: 739 - .saturating_add(Weight::from_ref_time(28_463 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 14_187 nanoseconds. + Weight::from_ref_time(16_680_582) + // Standard Error: 725 + .saturating_add(Weight::from_ref_time(27_134).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) // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { - // Minimum execution time: 34_231 nanoseconds. - Weight::from_ref_time(38_092_727 as u64) - // Standard Error: 1_309 - .saturating_add(Weight::from_ref_time(63_495 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 36_709 nanoseconds. + Weight::from_ref_time(40_268_669) + // Standard Error: 1_323 + .saturating_add(Weight::from_ref_time(64_240).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) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { - // Minimum execution time: 23_731 nanoseconds. - Weight::from_ref_time(27_777_697 as u64) - // Standard Error: 1_324 - .saturating_add(Weight::from_ref_time(64_783 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 25_833 nanoseconds. + Weight::from_ref_time(29_844_159) + // Standard Error: 1_243 + .saturating_add(Weight::from_ref_time(65_945).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/kusama/src/weights/pallet_im_online.rs b/runtime/kusama/src/weights/pallet_im_online.rs index 40452133a58e..24a91f168128 100644 --- a/runtime/kusama/src/weights/pallet_im_online.rs +++ b/runtime/kusama/src/weights/pallet_im_online.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_im_online` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -52,13 +52,13 @@ impl pallet_im_online::WeightInfo for WeightInfo { /// The range of component `k` is `[1, 1000]`. /// The range of component `e` is `[1, 100]`. fn validate_unsigned_and_then_heartbeat(k: u32, e: u32, ) -> Weight { - // Minimum execution time: 95_669 nanoseconds. - Weight::from_ref_time(76_845_572 as u64) - // Standard Error: 336 - .saturating_add(Weight::from_ref_time(23_690 as u64).saturating_mul(k as u64)) - // Standard Error: 3_386 - .saturating_add(Weight::from_ref_time(301_052 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 98_650 nanoseconds. + Weight::from_ref_time(80_236_257) + // Standard Error: 407 + .saturating_add(Weight::from_ref_time(24_048).saturating_mul(k.into())) + // Standard Error: 4_101 + .saturating_add(Weight::from_ref_time(313_664).saturating_mul(e.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/pallet_indices.rs b/runtime/kusama/src/weights/pallet_indices.rs index eebbd8d9062c..6715857e03e1 100644 --- a/runtime/kusama/src/weights/pallet_indices.rs +++ b/runtime/kusama/src/weights/pallet_indices.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_indices` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -46,39 +46,39 @@ pub struct WeightInfo(PhantomData); impl pallet_indices::WeightInfo for WeightInfo { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - // Minimum execution time: 24_874 nanoseconds. - Weight::from_ref_time(25_267_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_291 nanoseconds. + Weight::from_ref_time(26_869_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - // Minimum execution time: 31_488 nanoseconds. - Weight::from_ref_time(32_416_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 33_709 nanoseconds. + Weight::from_ref_time(34_356_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - // Minimum execution time: 26_255 nanoseconds. - Weight::from_ref_time(26_765_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 27_719 nanoseconds. + Weight::from_ref_time(28_586_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - // Minimum execution time: 26_642 nanoseconds. - Weight::from_ref_time(27_208_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 28_184 nanoseconds. + Weight::from_ref_time(28_751_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - // Minimum execution time: 31_472 nanoseconds. - Weight::from_ref_time(32_156_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 32_935 nanoseconds. + Weight::from_ref_time(33_696_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/pallet_membership.rs b/runtime/kusama/src/weights/pallet_membership.rs index 178470fe3aab..22be890c04a4 100644 --- a/runtime/kusama/src/weights/pallet_membership.rs +++ b/runtime/kusama/src/weights/pallet_membership.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_membership` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -50,12 +50,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 99]`. fn add_member(m: u32, ) -> Weight { - // Minimum execution time: 19_804 nanoseconds. - Weight::from_ref_time(20_453_376 as u64) - // Standard Error: 437 - .saturating_add(Weight::from_ref_time(35_454 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 21_152 nanoseconds. + Weight::from_ref_time(21_826_964) + // Standard Error: 463 + .saturating_add(Weight::from_ref_time(34_810).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -64,12 +64,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[2, 100]`. fn remove_member(m: u32, ) -> Weight { - // Minimum execution time: 21_784 nanoseconds. - Weight::from_ref_time(22_823_055 as u64) - // Standard Error: 643 - .saturating_add(Weight::from_ref_time(32_651 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 23_324 nanoseconds. + Weight::from_ref_time(24_070_746) + // Standard Error: 545 + .saturating_add(Weight::from_ref_time(33_705).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -78,12 +78,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[2, 100]`. fn swap_member(m: u32, ) -> Weight { - // Minimum execution time: 22_019 nanoseconds. - Weight::from_ref_time(23_226_698 as u64) - // Standard Error: 521 - .saturating_add(Weight::from_ref_time(44_518 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 23_348 nanoseconds. + Weight::from_ref_time(24_328_892) + // Standard Error: 550 + .saturating_add(Weight::from_ref_time(45_824).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -92,12 +92,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn reset_member(m: u32, ) -> Weight { - // Minimum execution time: 21_565 nanoseconds. - Weight::from_ref_time(22_510_625 as u64) - // Standard Error: 651 - .saturating_add(Weight::from_ref_time(154_739 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 22_834 nanoseconds. + Weight::from_ref_time(24_182_319) + // Standard Error: 812 + .saturating_add(Weight::from_ref_time(156_755).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -106,33 +106,33 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn change_key(m: u32, ) -> Weight { - // Minimum execution time: 22_059 nanoseconds. - Weight::from_ref_time(23_596_851 as u64) - // Standard Error: 634 - .saturating_add(Weight::from_ref_time(44_536 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 23_840 nanoseconds. + Weight::from_ref_time(25_086_525) + // Standard Error: 567 + .saturating_add(Weight::from_ref_time(44_882).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: TechnicalMembership Members (r:1 w:0) // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn set_prime(m: u32, ) -> Weight { - // Minimum execution time: 7_791 nanoseconds. - Weight::from_ref_time(8_349_224 as u64) - // Standard Error: 209 - .saturating_add(Weight::from_ref_time(8_473 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 8_200 nanoseconds. + Weight::from_ref_time(8_771_310) + // Standard Error: 235 + .saturating_add(Weight::from_ref_time(10_536).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn clear_prime(m: u32, ) -> Weight { - // Minimum execution time: 4_290 nanoseconds. - Weight::from_ref_time(4_687_392 as u64) - // Standard Error: 160 - .saturating_add(Weight::from_ref_time(288 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 4_759 nanoseconds. + Weight::from_ref_time(5_065_982) + // Standard Error: 129 + .saturating_add(Weight::from_ref_time(250).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/kusama/src/weights/pallet_multisig.rs b/runtime/kusama/src/weights/pallet_multisig.rs index b034fafcd8cc..6bb31f41bae6 100644 --- a/runtime/kusama/src/weights/pallet_multisig.rs +++ b/runtime/kusama/src/weights/pallet_multisig.rs @@ -16,8 +16,8 @@ //! Autogenerated weights for `pallet_multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-26, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bm2`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 // Executed Command: @@ -28,11 +28,11 @@ // --steps=50 // --repeat=20 // --pallet=pallet_multisig -// --extrinsic= +// --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --header=./file_header.txt -// --output=runtime/kusama/src/weights/ +// --output=./runtime/kusama/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -46,81 +46,81 @@ pub struct WeightInfo(PhantomData); impl pallet_multisig::WeightInfo for WeightInfo { /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { - // Minimum execution time: 14_233 nanoseconds. - Weight::from_ref_time(14_763_390 as u64) - // Standard Error: 2 - .saturating_add(Weight::from_ref_time(479 as u64).saturating_mul(z as u64)) + // Minimum execution time: 14_686 nanoseconds. + Weight::from_ref_time(15_171_154) + // Standard Error: 7 + .saturating_add(Weight::from_ref_time(546).saturating_mul(z.into())) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) /// 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 { - // Minimum execution time: 42_837 nanoseconds. - Weight::from_ref_time(34_846_149 as u64) - // Standard Error: 646 - .saturating_add(Weight::from_ref_time(89_482 as u64).saturating_mul(s as u64)) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(1_465 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 45_066 nanoseconds. + Weight::from_ref_time(37_346_773) + // Standard Error: 847 + .saturating_add(Weight::from_ref_time(89_091).saturating_mul(s.into())) + // Standard Error: 8 + .saturating_add(Weight::from_ref_time(1_534).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Multisig Multisigs (r:1 w:1) /// 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 { - // Minimum execution time: 32_269 nanoseconds. - Weight::from_ref_time(25_447_784 as u64) - // Standard Error: 499 - .saturating_add(Weight::from_ref_time(74_525 as u64).saturating_mul(s as u64)) - // Standard Error: 4 - .saturating_add(Weight::from_ref_time(1_457 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 34_578 nanoseconds. + Weight::from_ref_time(26_735_629) + // Standard Error: 745 + .saturating_add(Weight::from_ref_time(83_969).saturating_mul(s.into())) + // Standard Error: 7 + .saturating_add(Weight::from_ref_time(1_569).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) // Storage: System Account (r:1 w:1) /// 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 { - // Minimum execution time: 46_096 nanoseconds. - Weight::from_ref_time(37_139_587 as u64) - // Standard Error: 602 - .saturating_add(Weight::from_ref_time(104_199 as u64).saturating_mul(s as u64)) + // Minimum execution time: 49_448 nanoseconds. + Weight::from_ref_time(39_931_812) + // Standard Error: 556 + .saturating_add(Weight::from_ref_time(108_692).saturating_mul(s.into())) // Standard Error: 5 - .saturating_add(Weight::from_ref_time(1_478 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(1_554).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) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { - // Minimum execution time: 31_572 nanoseconds. - Weight::from_ref_time(33_475_485 as u64) - // Standard Error: 972 - .saturating_add(Weight::from_ref_time(91_041 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 33_550 nanoseconds. + Weight::from_ref_time(36_004_994) + // Standard Error: 1_074 + .saturating_add(Weight::from_ref_time(89_359).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Multisig Multisigs (r:1 w:1) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { - // Minimum execution time: 21_861 nanoseconds. - Weight::from_ref_time(23_986_670 as u64) - // Standard Error: 660 - .saturating_add(Weight::from_ref_time(79_765 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 23_854 nanoseconds. + Weight::from_ref_time(25_907_514) + // Standard Error: 727 + .saturating_add(Weight::from_ref_time(80_801).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) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { - // Minimum execution time: 31_375 nanoseconds. - Weight::from_ref_time(33_657_765 as u64) - // Standard Error: 931 - .saturating_add(Weight::from_ref_time(84_177 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 34_205 nanoseconds. + Weight::from_ref_time(36_711_168) + // Standard Error: 938 + .saturating_add(Weight::from_ref_time(83_514).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/pallet_nis.rs b/runtime/kusama/src/weights/pallet_nis.rs new file mode 100644 index 000000000000..2c8d14990c46 --- /dev/null +++ b/runtime/kusama/src/weights/pallet_nis.rs @@ -0,0 +1,120 @@ +// Copyright 2017-2022 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_nis` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot +// benchmark +// pallet +// --chain=kusama-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_nis +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_nis`. +pub struct WeightInfo(PhantomData); +impl pallet_nis::WeightInfo for WeightInfo { + // Storage: Nis Queues (r:1 w:1) + // Storage: Nis QueueTotals (r:1 w:1) + /// The range of component `l` is `[0, 999]`. + fn place_bid(l: u32, ) -> Weight { + // Minimum execution time: 34_088 nanoseconds. + Weight::from_ref_time(36_343_273) + // Standard Error: 733 + .saturating_add(Weight::from_ref_time(72_985).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: Nis Queues (r:1 w:1) + // Storage: Nis QueueTotals (r:1 w:1) + fn place_bid_max() -> Weight { + // Minimum execution time: 105_579 nanoseconds. + Weight::from_ref_time(107_541_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: Nis Queues (r:1 w:1) + // Storage: Nis QueueTotals (r:1 w:1) + /// The range of component `l` is `[1, 1000]`. + fn retract_bid(l: u32, ) -> Weight { + // Minimum execution time: 42_023 nanoseconds. + Weight::from_ref_time(37_884_296) + // Standard Error: 707 + .saturating_add(Weight::from_ref_time(61_455).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: Nis Summary (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn fund_deficit() -> Weight { + // Minimum execution time: 41_848 nanoseconds. + Weight::from_ref_time(42_431_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + // Storage: Nis Receipts (r:1 w:1) + // Storage: Nis Summary (r:1 w:1) + // Storage: NisCounterpartBalances Account (r:1 w:1) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn thaw() -> Weight { + // Minimum execution time: 63_268 nanoseconds. + Weight::from_ref_time(64_073_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } + // Storage: Nis Summary (r:1 w:1) + // Storage: System Account (r:1 w:0) + // Storage: Nis QueueTotals (r:1 w:1) + fn process_queues() -> Weight { + // Minimum execution time: 36_969 nanoseconds. + Weight::from_ref_time(38_199_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: Nis Queues (r:1 w:1) + fn process_queue() -> Weight { + // Minimum execution time: 4_219 nanoseconds. + Weight::from_ref_time(4_402_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + // Storage: System Account (r:1 w:0) + // Storage: Nis Receipts (r:0 w:1) + fn process_bid() -> Weight { + // Minimum execution time: 13_211 nanoseconds. + Weight::from_ref_time(13_655_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/runtime/kusama/src/weights/pallet_nomination_pools.rs b/runtime/kusama/src/weights/pallet_nomination_pools.rs index 57e4a54f3584..23a5a0a0fe51 100644 --- a/runtime/kusama/src/weights/pallet_nomination_pools.rs +++ b/runtime/kusama/src/weights/pallet_nomination_pools.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_nomination_pools` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -47,65 +47,66 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools MinJoinBond (r:1 w:0) // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:2 w:1) // Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) // Storage: NominationPools MaxPoolMembers (r:1 w:0) // Storage: NominationPools CounterForPoolMembers (r:1 w:1) - // Storage: Staking Bonded (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn join() -> Weight { - // Minimum execution time: 138_890 nanoseconds. - Weight::from_ref_time(139_862_000 as u64) - .saturating_add(T::DbWeight::get().reads(17 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) + // Minimum execution time: 143_547 nanoseconds. + Weight::from_ref_time(145_024_000) + .saturating_add(T::DbWeight::get().reads(17)) + .saturating_add(T::DbWeight::get().writes(12)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:3 w:2) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra_transfer() -> Weight { - // Minimum execution time: 138_685 nanoseconds. - Weight::from_ref_time(139_666_000 as u64) - .saturating_add(T::DbWeight::get().reads(14 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) + // Minimum execution time: 142_015 nanoseconds. + Weight::from_ref_time(143_485_000) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(12)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:3 w:3) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:2 w:2) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra_reward() -> Weight { - // Minimum execution time: 138_114 nanoseconds. - Weight::from_ref_time(141_132_000 as u64) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) + // Minimum execution time: 144_390 nanoseconds. + Weight::from_ref_time(145_612_000) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(12)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:1 w:1) fn claim_payout() -> Weight { - // Minimum execution time: 54_174 nanoseconds. - Weight::from_ref_time(54_785_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 56_638 nanoseconds. + Weight::from_ref_time(57_158_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: System Account (r:2 w:1) // Storage: Staking CurrentEra (r:1 w:0) @@ -113,52 +114,53 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: Staking MinNominatorBond (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:3 w:3) - // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListBags (r:2 w:2) // Storage: NominationPools SubPoolsStorage (r:1 w:1) // Storage: NominationPools CounterForSubPoolsStorage (r:1 w:1) fn unbond() -> Weight { - // Minimum execution time: 137_752 nanoseconds. - Weight::from_ref_time(139_045_000 as u64) - .saturating_add(T::DbWeight::get().reads(18 as u64)) - .saturating_add(T::DbWeight::get().writes(13 as u64)) + // Minimum execution time: 147_898 nanoseconds. + Weight::from_ref_time(148_831_000) + .saturating_add(T::DbWeight::get().reads(18)) + .saturating_add(T::DbWeight::get().writes(13)) } // Storage: NominationPools BondedPools (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Balances Locks (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { - // Minimum execution time: 49_665 nanoseconds. - Weight::from_ref_time(51_537_967 as u64) - // Standard Error: 937 - .saturating_add(Weight::from_ref_time(19_269 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 57_587 nanoseconds. + Weight::from_ref_time(59_622_292) + // Standard Error: 1_367 + .saturating_add(Weight::from_ref_time(10_795).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools SubPoolsStorage (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) // Storage: NominationPools CounterForPoolMembers (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 89_456 nanoseconds. - Weight::from_ref_time(92_464_998 as u64) - // Standard Error: 1_616 - .saturating_add(Weight::from_ref_time(21_615 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 98_065 nanoseconds. + Weight::from_ref_time(99_968_288) + // Standard Error: 1_683 + .saturating_add(Weight::from_ref_time(34_131).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools SubPoolsStorage (r:1 w:1) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) // Storage: Staking SlashingSpans (r:1 w:0) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:0) @@ -174,25 +176,27 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools CounterForBondedPools (r:1 w:1) // Storage: Staking Payee (r:0 w:1) /// The range of component `s` is `[0, 100]`. - fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - // Minimum execution time: 142_468 nanoseconds. - Weight::from_ref_time(145_865_382 as u64) - .saturating_add(T::DbWeight::get().reads(20 as u64)) - .saturating_add(T::DbWeight::get().writes(17 as u64)) + fn withdraw_unbonded_kill(s: u32, ) -> Weight { + // Minimum execution time: 147_965 nanoseconds. + Weight::from_ref_time(150_852_299) + // Standard Error: 2_753 + .saturating_add(Weight::from_ref_time(3_913).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(20)) + .saturating_add(T::DbWeight::get().writes(17)) } + // Storage: NominationPools LastPoolId (r:1 w:1) // Storage: Staking MinNominatorBond (r:1 w:0) // Storage: NominationPools MinCreateBond (r:1 w:0) // Storage: NominationPools MinJoinBond (r:1 w:0) // Storage: NominationPools MaxPools (r:1 w:0) // Storage: NominationPools CounterForBondedPools (r:1 w:1) // Storage: NominationPools PoolMembers (r:1 w:1) - // Storage: NominationPools LastPoolId (r:1 w:1) // Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) // Storage: NominationPools MaxPoolMembers (r:1 w:0) // Storage: NominationPools CounterForPoolMembers (r:1 w:1) // Storage: System Account (r:2 w:2) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) @@ -202,52 +206,53 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools BondedPools (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn create() -> Weight { - // Minimum execution time: 126_922 nanoseconds. - Weight::from_ref_time(128_840_000 as u64) - .saturating_add(T::DbWeight::get().reads(21 as u64)) - .saturating_add(T::DbWeight::get().writes(15 as u64)) + // Minimum execution time: 132_292 nanoseconds. + Weight::from_ref_time(133_042_000) + .saturating_add(T::DbWeight::get().reads(21)) + .saturating_add(T::DbWeight::get().writes(15)) } // Storage: NominationPools BondedPools (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinNominatorBond (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) // Storage: Staking MaxNominatorsCount (r:1 w:0) // Storage: Staking Validators (r:2 w:0) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListNodes (r:1 w:1) // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 24]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 62_487 nanoseconds. - Weight::from_ref_time(62_210_788 as u64) - // Standard Error: 4_540 - .saturating_add(Weight::from_ref_time(995_413 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 64_126 nanoseconds. + Weight::from_ref_time(63_915_647) + // Standard Error: 5_090 + .saturating_add(Weight::from_ref_time(1_101_848).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: NominationPools BondedPools (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) fn set_state() -> Weight { - // Minimum execution time: 34_398 nanoseconds. - Weight::from_ref_time(34_691_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 39_910 nanoseconds. + Weight::from_ref_time(40_322_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: NominationPools BondedPools (r:1 w:0) // Storage: NominationPools Metadata (r:1 w:1) // Storage: NominationPools CounterForMetadata (r:1 w:1) /// The range of component `n` is `[1, 256]`. fn set_metadata(n: u32, ) -> Weight { - // Minimum execution time: 16_304 nanoseconds. - Weight::from_ref_time(17_385_094 as u64) - // Standard Error: 695 - .saturating_add(Weight::from_ref_time(451 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 15_767 nanoseconds. + Weight::from_ref_time(16_412_468) + // Standard Error: 137 + .saturating_add(Weight::from_ref_time(2_002).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: NominationPools MinJoinBond (r:0 w:1) // Storage: NominationPools MaxPoolMembers (r:0 w:1) @@ -255,18 +260,19 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools MinCreateBond (r:0 w:1) // Storage: NominationPools MaxPools (r:0 w:1) fn set_configs() -> Weight { - // Minimum execution time: 7_357 nanoseconds. - Weight::from_ref_time(7_670_000 as u64) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 6_483 nanoseconds. + Weight::from_ref_time(6_886_000) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: NominationPools BondedPools (r:1 w:1) fn update_roles() -> Weight { - // Minimum execution time: 26_355 nanoseconds. - Weight::from_ref_time(26_659_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 25_553 nanoseconds. + Weight::from_ref_time(26_137_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: NominationPools BondedPools (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -275,9 +281,9 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Minimum execution time: 60_060 nanoseconds. - Weight::from_ref_time(61_928_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 65_005 nanoseconds. + Weight::from_ref_time(65_854_000) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(5)) } } diff --git a/runtime/kusama/src/weights/pallet_preimage.rs b/runtime/kusama/src/weights/pallet_preimage.rs index ac32acb41730..5e60b6b837a9 100644 --- a/runtime/kusama/src/weights/pallet_preimage.rs +++ b/runtime/kusama/src/weights/pallet_preimage.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_preimage` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -48,99 +48,99 @@ impl pallet_preimage::WeightInfo for WeightInfo { // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { - // Minimum execution time: 28_176 nanoseconds. - Weight::from_ref_time(28_451_000 as u64) + // Minimum execution time: 29_673 nanoseconds. + Weight::from_ref_time(29_855_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_294 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_331).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { - // Minimum execution time: 19_071 nanoseconds. - Weight::from_ref_time(19_336_000 as u64) + // Minimum execution time: 20_825 nanoseconds. + Weight::from_ref_time(21_118_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_293 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_331).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { - // Minimum execution time: 17_392 nanoseconds. - Weight::from_ref_time(17_712_000 as u64) + // Minimum execution time: 19_288 nanoseconds. + Weight::from_ref_time(19_588_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_294 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_328).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_preimage() -> Weight { - // Minimum execution time: 37_996 nanoseconds. - Weight::from_ref_time(39_555_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_537 nanoseconds. + Weight::from_ref_time(42_873_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_no_deposit_preimage() -> Weight { - // Minimum execution time: 27_044 nanoseconds. - Weight::from_ref_time(28_069_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 29_369 nanoseconds. + Weight::from_ref_time(30_548_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_preimage() -> Weight { - // Minimum execution time: 26_233 nanoseconds. - Weight::from_ref_time(27_659_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 28_536 nanoseconds. + Weight::from_ref_time(29_659_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_no_deposit_preimage() -> Weight { - // Minimum execution time: 14_540 nanoseconds. - Weight::from_ref_time(16_040_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_553 nanoseconds. + Weight::from_ref_time(16_115_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_unnoted_preimage() -> Weight { - // Minimum execution time: 16_930 nanoseconds. - Weight::from_ref_time(17_887_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 18_213 nanoseconds. + Weight::from_ref_time(18_899_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_requested_preimage() -> Weight { - // Minimum execution time: 7_707 nanoseconds. - Weight::from_ref_time(8_173_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_660 nanoseconds. + Weight::from_ref_time(9_003_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_preimage() -> Weight { - // Minimum execution time: 26_963 nanoseconds. - Weight::from_ref_time(28_167_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 28_711 nanoseconds. + Weight::from_ref_time(29_498_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_unnoted_preimage() -> Weight { - // Minimum execution time: 7_845 nanoseconds. - Weight::from_ref_time(8_128_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_514 nanoseconds. + Weight::from_ref_time(9_156_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_multi_referenced_preimage() -> Weight { - // Minimum execution time: 7_894 nanoseconds. - Weight::from_ref_time(8_185_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_710 nanoseconds. + Weight::from_ref_time(8_882_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/pallet_proxy.rs b/runtime/kusama/src/weights/pallet_proxy.rs index e950db5bce6d..98c2bc9790e6 100644 --- a/runtime/kusama/src/weights/pallet_proxy.rs +++ b/runtime/kusama/src/weights/pallet_proxy.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_proxy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -47,11 +47,11 @@ impl pallet_proxy::WeightInfo for WeightInfo { // Storage: Proxy Proxies (r:1 w:0) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { - // Minimum execution time: 19_551 nanoseconds. - Weight::from_ref_time(20_748_848 as u64) - // Standard Error: 1_568 - .saturating_add(Weight::from_ref_time(54_200 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 20_875 nanoseconds. + Weight::from_ref_time(21_838_757) + // Standard Error: 1_752 + .saturating_add(Weight::from_ref_time(53_895).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) @@ -59,38 +59,40 @@ impl pallet_proxy::WeightInfo for WeightInfo { /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 37_257 nanoseconds. - Weight::from_ref_time(37_245_921 as u64) - // Standard Error: 1_877 - .saturating_add(Weight::from_ref_time(116_373 as u64).saturating_mul(a as u64)) - // Standard Error: 1_939 - .saturating_add(Weight::from_ref_time(40_239 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 38_838 nanoseconds. + Weight::from_ref_time(39_611_649) + // Standard Error: 3_025 + .saturating_add(Weight::from_ref_time(121_515).saturating_mul(a.into())) + // Standard Error: 3_125 + .saturating_add(Weight::from_ref_time(36_334).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) // Storage: System Account (r:1 w:1) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn remove_announcement(a: u32, _p: u32, ) -> Weight { - // Minimum execution time: 25_864 nanoseconds. - Weight::from_ref_time(26_440_498 as u64) - // Standard Error: 1_682 - .saturating_add(Weight::from_ref_time(114_225 as u64).saturating_mul(a as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 27_406 nanoseconds. + Weight::from_ref_time(28_708_194) + // Standard Error: 1_921 + .saturating_add(Weight::from_ref_time(111_792).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) // Storage: System Account (r:1 w:1) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. - fn reject_announcement(a: u32, _p: u32, ) -> Weight { - // Minimum execution time: 25_392 nanoseconds. - Weight::from_ref_time(26_349_515 as u64) - // Standard Error: 1_456 - .saturating_add(Weight::from_ref_time(113_602 as u64).saturating_mul(a as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + fn reject_announcement(a: u32, p: u32, ) -> Weight { + // Minimum execution time: 27_062 nanoseconds. + Weight::from_ref_time(28_563_015) + // Standard Error: 1_659 + .saturating_add(Weight::from_ref_time(113_351).saturating_mul(a.into())) + // Standard Error: 1_714 + .saturating_add(Weight::from_ref_time(1_980).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) // Storage: Proxy Announcements (r:1 w:1) @@ -98,64 +100,64 @@ impl pallet_proxy::WeightInfo for WeightInfo { /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 33_187 nanoseconds. - Weight::from_ref_time(34_423_105 as u64) - // Standard Error: 1_973 - .saturating_add(Weight::from_ref_time(104_655 as u64).saturating_mul(a as u64)) - // Standard Error: 2_039 - .saturating_add(Weight::from_ref_time(27_773 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 35_157 nanoseconds. + Weight::from_ref_time(36_604_315) + // Standard Error: 1_726 + .saturating_add(Weight::from_ref_time(116_828).saturating_mul(a.into())) + // Standard Error: 1_784 + .saturating_add(Weight::from_ref_time(20_900).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) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { - // Minimum execution time: 27_189 nanoseconds. - Weight::from_ref_time(28_582_470 as u64) - // Standard Error: 2_064 - .saturating_add(Weight::from_ref_time(63_883 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_002 nanoseconds. + Weight::from_ref_time(30_575_852) + // Standard Error: 3_808 + .saturating_add(Weight::from_ref_time(72_738).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) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { - // Minimum execution time: 26_366 nanoseconds. - Weight::from_ref_time(28_374_822 as u64) - // Standard Error: 2_182 - .saturating_add(Weight::from_ref_time(82_251 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 28_573 nanoseconds. + Weight::from_ref_time(30_518_220) + // Standard Error: 2_094 + .saturating_add(Weight::from_ref_time(82_748).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) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { - // Minimum execution time: 22_910 nanoseconds. - Weight::from_ref_time(25_215_950 as u64) - // Standard Error: 3_028 - .saturating_add(Weight::from_ref_time(25_900 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 24_806 nanoseconds. + Weight::from_ref_time(26_467_137) + // Standard Error: 1_847 + .saturating_add(Weight::from_ref_time(50_597).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) // Storage: Proxy Proxies (r:1 w:1) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { - // Minimum execution time: 30_126 nanoseconds. - Weight::from_ref_time(31_650_457 as u64) - // Standard Error: 1_924 - .saturating_add(Weight::from_ref_time(21_491 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 32_043 nanoseconds. + Weight::from_ref_time(33_493_950) + // Standard Error: 1_834 + .saturating_add(Weight::from_ref_time(28_149).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Proxy Proxies (r:1 w:1) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { - // Minimum execution time: 24_510 nanoseconds. - Weight::from_ref_time(25_823_835 as u64) - // Standard Error: 1_747 - .saturating_add(Weight::from_ref_time(46_717 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_446 nanoseconds. + Weight::from_ref_time(27_736_383) + // Standard Error: 1_891 + .saturating_add(Weight::from_ref_time(47_499).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/pallet_ranked_collective.rs b/runtime/kusama/src/weights/pallet_ranked_collective.rs index 0f7a13150b82..6ba001f2b4c5 100644 --- a/runtime/kusama/src/weights/pallet_ranked_collective.rs +++ b/runtime/kusama/src/weights/pallet_ranked_collective.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_ranked_collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -49,10 +49,10 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Storage: FellowshipCollective IndexToId (r:0 w:1) // Storage: FellowshipCollective IdToIndex (r:0 w:1) fn add_member() -> Weight { - // Minimum execution time: 18_900 nanoseconds. - Weight::from_ref_time(19_302_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 20_783 nanoseconds. + Weight::from_ref_time(21_534_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: FellowshipCollective Members (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:1) @@ -60,14 +60,14 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Storage: FellowshipCollective IndexToId (r:1 w:1) /// The range of component `r` is `[0, 10]`. fn remove_member(r: u32, ) -> Weight { - // Minimum execution time: 29_913 nanoseconds. - Weight::from_ref_time(32_149_860 as u64) - // Standard Error: 25_258 - .saturating_add(Weight::from_ref_time(9_512_553 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(r as u64))) + // Minimum execution time: 32_177 nanoseconds. + Weight::from_ref_time(34_744_578) + // Standard Error: 21_214 + .saturating_add(Weight::from_ref_time(10_025_635).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(4)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(r.into()))) } // Storage: FellowshipCollective Members (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:1) @@ -75,12 +75,12 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Storage: FellowshipCollective IdToIndex (r:0 w:1) /// The range of component `r` is `[0, 10]`. fn promote_member(r: u32, ) -> Weight { - // Minimum execution time: 21_327 nanoseconds. - Weight::from_ref_time(22_411_852 as u64) - // Standard Error: 3_902 - .saturating_add(Weight::from_ref_time(457_216 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 23_280 nanoseconds. + Weight::from_ref_time(24_473_719) + // Standard Error: 5_281 + .saturating_add(Weight::from_ref_time(464_452).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: FellowshipCollective Members (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:1) @@ -88,33 +88,33 @@ impl pallet_ranked_collective::WeightInfo for WeightInf // Storage: FellowshipCollective IndexToId (r:1 w:1) /// The range of component `r` is `[0, 10]`. fn demote_member(r: u32, ) -> Weight { - // Minimum execution time: 29_563 nanoseconds. - Weight::from_ref_time(32_287_027 as u64) - // Standard Error: 15_398 - .saturating_add(Weight::from_ref_time(639_177 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 32_351 nanoseconds. + Weight::from_ref_time(34_734_099) + // Standard Error: 15_729 + .saturating_add(Weight::from_ref_time(644_092).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: FellowshipCollective Members (r:1 w:0) // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipCollective Voting (r:1 w:1) // Storage: Scheduler Agenda (r:2 w:2) fn vote() -> Weight { - // Minimum execution time: 45_461 nanoseconds. - Weight::from_ref_time(46_094_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 47_216 nanoseconds. + Weight::from_ref_time(47_698_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:0) // Storage: FellowshipCollective VotingCleanup (r:1 w:0) // Storage: FellowshipCollective Voting (r:0 w:2) /// The range of component `n` is `[0, 100]`. fn cleanup_poll(n: u32, ) -> Weight { - // Minimum execution time: 14_374 nanoseconds. - Weight::from_ref_time(18_663_988 as u64) - // Standard Error: 1_622 - .saturating_add(Weight::from_ref_time(866_964 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(n as u64))) + // Minimum execution time: 15_139 nanoseconds. + Weight::from_ref_time(19_621_273) + // Standard Error: 2_430 + .saturating_add(Weight::from_ref_time(906_348).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) } } diff --git a/runtime/kusama/src/weights/pallet_referenda_fellowship_referenda.rs b/runtime/kusama/src/weights/pallet_referenda_fellowship_referenda.rs index 07f201334a84..82ae8e450520 100644 --- a/runtime/kusama/src/weights/pallet_referenda_fellowship_referenda.rs +++ b/runtime/kusama/src/weights/pallet_referenda_fellowship_referenda.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_referenda` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -49,241 +49,248 @@ impl pallet_referenda::WeightInfo for WeightInfo { // Storage: Scheduler Agenda (r:1 w:1) // Storage: FellowshipReferenda ReferendumInfoFor (r:0 w:1) fn submit() -> Weight { - // Minimum execution time: 32_180 nanoseconds. - Weight::from_ref_time(32_746_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 32_920 nanoseconds. + Weight::from_ref_time(33_284_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:2 w:2) fn place_decision_deposit_preparing() -> Weight { - // Minimum execution time: 47_785 nanoseconds. - Weight::from_ref_time(48_489_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 49_609 nanoseconds. + Weight::from_ref_time(50_258_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda DecidingCount (r:1 w:0) // Storage: FellowshipReferenda TrackQueue (r:1 w:1) fn place_decision_deposit_queued() -> Weight { - // Minimum execution time: 83_684 nanoseconds. - Weight::from_ref_time(87_530_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 86_531 nanoseconds. + Weight::from_ref_time(89_289_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda DecidingCount (r:1 w:0) // Storage: FellowshipReferenda TrackQueue (r:1 w:1) fn place_decision_deposit_not_queued() -> Weight { - // Minimum execution time: 84_154 nanoseconds. - Weight::from_ref_time(87_244_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 84_542 nanoseconds. + Weight::from_ref_time(88_503_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda DecidingCount (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:2 w:2) fn place_decision_deposit_passing() -> Weight { - // Minimum execution time: 185_392 nanoseconds. - Weight::from_ref_time(197_854_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 187_769 nanoseconds. + Weight::from_ref_time(197_368_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda DecidingCount (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) fn place_decision_deposit_failing() -> Weight { - // Minimum execution time: 43_545 nanoseconds. - Weight::from_ref_time(44_652_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 44_940 nanoseconds. + Weight::from_ref_time(45_509_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) fn refund_decision_deposit() -> Weight { - // Minimum execution time: 31_072 nanoseconds. - Weight::from_ref_time(31_477_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 32_474 nanoseconds. + Weight::from_ref_time(33_307_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) + fn refund_submission_deposit() -> Weight { + // Minimum execution time: 21_301 nanoseconds. + Weight::from_ref_time(21_708_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:2 w:2) fn cancel() -> Weight { - // Minimum execution time: 38_167 nanoseconds. - Weight::from_ref_time(38_765_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 39_139 nanoseconds. + Weight::from_ref_time(39_763_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:2 w:2) fn kill() -> Weight { - // Minimum execution time: 67_286 nanoseconds. - Weight::from_ref_time(69_089_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 69_562 nanoseconds. + Weight::from_ref_time(70_414_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: FellowshipReferenda TrackQueue (r:1 w:0) // Storage: FellowshipReferenda DecidingCount (r:1 w:1) fn one_fewer_deciding_queue_empty() -> Weight { - // Minimum execution time: 11_019 nanoseconds. - Weight::from_ref_time(11_370_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_930 nanoseconds. + Weight::from_ref_time(12_215_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: FellowshipReferenda TrackQueue (r:1 w:1) // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:2 w:2) fn one_fewer_deciding_failing() -> Weight { - // Minimum execution time: 120_874 nanoseconds. - Weight::from_ref_time(123_568_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 119_239 nanoseconds. + Weight::from_ref_time(122_514_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: FellowshipReferenda TrackQueue (r:1 w:1) // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:2 w:2) fn one_fewer_deciding_passing() -> Weight { - // Minimum execution time: 121_845 nanoseconds. - Weight::from_ref_time(125_055_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 121_229 nanoseconds. + Weight::from_ref_time(124_603_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda TrackQueue (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:0) fn nudge_referendum_requeued_insertion() -> Weight { - // Minimum execution time: 88_879 nanoseconds. - Weight::from_ref_time(91_415_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 85_568 nanoseconds. + Weight::from_ref_time(89_360_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda TrackQueue (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:0) fn nudge_referendum_requeued_slide() -> Weight { - // Minimum execution time: 87_283 nanoseconds. - Weight::from_ref_time(90_994_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 85_888 nanoseconds. + Weight::from_ref_time(88_278_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda DecidingCount (r:1 w:0) // Storage: FellowshipReferenda TrackQueue (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:0) fn nudge_referendum_queued() -> Weight { - // Minimum execution time: 91_243 nanoseconds. - Weight::from_ref_time(93_680_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 87_650 nanoseconds. + Weight::from_ref_time(91_112_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda DecidingCount (r:1 w:0) // Storage: FellowshipReferenda TrackQueue (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:0) fn nudge_referendum_not_queued() -> Weight { - // Minimum execution time: 90_166 nanoseconds. - Weight::from_ref_time(93_331_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 88_830 nanoseconds. + Weight::from_ref_time(91_640_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_no_deposit() -> Weight { - // Minimum execution time: 29_373 nanoseconds. - Weight::from_ref_time(30_186_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 29_867 nanoseconds. + Weight::from_ref_time(30_807_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_preparing() -> Weight { - // Minimum execution time: 30_715 nanoseconds. - Weight::from_ref_time(31_405_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 31_137 nanoseconds. + Weight::from_ref_time(31_567_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) fn nudge_referendum_timed_out() -> Weight { - // Minimum execution time: 22_200 nanoseconds. - Weight::from_ref_time(23_053_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 23_001 nanoseconds. + Weight::from_ref_time(23_825_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda DecidingCount (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_begin_deciding_failing() -> Weight { - // Minimum execution time: 41_344 nanoseconds. - Weight::from_ref_time(42_020_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 42_509 nanoseconds. + Weight::from_ref_time(42_964_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipReferenda DecidingCount (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_begin_deciding_passing() -> Weight { - // Minimum execution time: 86_079 nanoseconds. - Weight::from_ref_time(89_646_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 86_839 nanoseconds. + Weight::from_ref_time(89_589_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_begin_confirming() -> Weight { - // Minimum execution time: 146_594 nanoseconds. - Weight::from_ref_time(167_523_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 153_039 nanoseconds. + Weight::from_ref_time(167_549_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_end_confirming() -> Weight { - // Minimum execution time: 163_366 nanoseconds. - Weight::from_ref_time(169_474_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 150_316 nanoseconds. + Weight::from_ref_time(169_539_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_continue_not_confirming() -> Weight { - // Minimum execution time: 157_952 nanoseconds. - Weight::from_ref_time(163_326_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 159_327 nanoseconds. + Weight::from_ref_time(165_221_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_continue_confirming() -> Weight { - // Minimum execution time: 81_994 nanoseconds. - Weight::from_ref_time(83_855_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 80_839 nanoseconds. + Weight::from_ref_time(84_645_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:2 w:2) // Storage: Scheduler Lookup (r:1 w:1) fn nudge_referendum_approved() -> Weight { - // Minimum execution time: 173_094 nanoseconds. - Weight::from_ref_time(178_850_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 159_227 nanoseconds. + Weight::from_ref_time(181_444_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: FellowshipReferenda ReferendumInfoFor (r:1 w:1) // Storage: FellowshipCollective MemberCount (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_rejected() -> Weight { - // Minimum execution time: 162_813 nanoseconds. - Weight::from_ref_time(167_908_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 163_023 nanoseconds. + Weight::from_ref_time(171_393_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/kusama/src/weights/pallet_referenda_referenda.rs b/runtime/kusama/src/weights/pallet_referenda_referenda.rs index b74656db71bb..6020ba33e057 100644 --- a/runtime/kusama/src/weights/pallet_referenda_referenda.rs +++ b/runtime/kusama/src/weights/pallet_referenda_referenda.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_referenda` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -48,229 +48,248 @@ impl pallet_referenda::WeightInfo for WeightInfo { // Storage: Scheduler Agenda (r:1 w:1) // Storage: Referenda ReferendumInfoFor (r:0 w:1) fn submit() -> Weight { - // Minimum execution time: 36_837 nanoseconds. - Weight::from_ref_time(37_648_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 37_755 nanoseconds. + Weight::from_ref_time(38_346_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:2 w:2) fn place_decision_deposit_preparing() -> Weight { - // Minimum execution time: 46_630 nanoseconds. - Weight::from_ref_time(47_953_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 48_492 nanoseconds. + Weight::from_ref_time(49_586_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda DecidingCount (r:1 w:0) // Storage: Referenda TrackQueue (r:1 w:1) fn place_decision_deposit_queued() -> Weight { - // Minimum execution time: 48_191 nanoseconds. - Weight::from_ref_time(49_124_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 50_416 nanoseconds. + Weight::from_ref_time(51_153_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda DecidingCount (r:1 w:0) // Storage: Referenda TrackQueue (r:1 w:1) fn place_decision_deposit_not_queued() -> Weight { - // Minimum execution time: 47_992 nanoseconds. - Weight::from_ref_time(48_678_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 49_940 nanoseconds. + Weight::from_ref_time(50_664_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:2 w:2) fn place_decision_deposit_passing() -> Weight { - // Minimum execution time: 59_996 nanoseconds. - Weight::from_ref_time(62_060_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 63_167 nanoseconds. + Weight::from_ref_time(64_982_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) fn place_decision_deposit_failing() -> Weight { - // Minimum execution time: 42_021 nanoseconds. - Weight::from_ref_time(43_451_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 44_569 nanoseconds. + Weight::from_ref_time(46_163_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) fn refund_decision_deposit() -> Weight { - // Minimum execution time: 30_016 nanoseconds. - Weight::from_ref_time(30_902_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 31_451 nanoseconds. + Weight::from_ref_time(32_309_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + // Storage: Referenda ReferendumInfoFor (r:1 w:1) + fn refund_submission_deposit() -> Weight { + // Minimum execution time: 30_259 nanoseconds. + Weight::from_ref_time(30_856_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:2 w:2) fn cancel() -> Weight { - // Minimum execution time: 37_205 nanoseconds. - Weight::from_ref_time(38_401_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 38_179 nanoseconds. + Weight::from_ref_time(39_326_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:2 w:2) fn kill() -> Weight { - // Minimum execution time: 77_049 nanoseconds. - Weight::from_ref_time(79_005_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 79_978 nanoseconds. + Weight::from_ref_time(80_846_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Referenda TrackQueue (r:1 w:0) // Storage: Referenda DecidingCount (r:1 w:1) fn one_fewer_deciding_queue_empty() -> Weight { - // Minimum execution time: 11_084 nanoseconds. - Weight::from_ref_time(11_351_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_591 nanoseconds. + Weight::from_ref_time(12_103_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Referenda TrackQueue (r:1 w:1) // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:2 w:2) fn one_fewer_deciding_failing() -> Weight { - // Minimum execution time: 77_869 nanoseconds. - Weight::from_ref_time(78_497_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 78_771 nanoseconds. + Weight::from_ref_time(79_849_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Referenda TrackQueue (r:1 w:1) // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:2 w:2) fn one_fewer_deciding_passing() -> Weight { - // Minimum execution time: 79_673 nanoseconds. - Weight::from_ref_time(80_484_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 80_373 nanoseconds. + Weight::from_ref_time(81_121_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda TrackQueue (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:0) fn nudge_referendum_requeued_insertion() -> Weight { - // Minimum execution time: 54_937 nanoseconds. - Weight::from_ref_time(55_487_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 53_641 nanoseconds. + Weight::from_ref_time(54_278_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda TrackQueue (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:0) fn nudge_referendum_requeued_slide() -> Weight { - // Minimum execution time: 54_611 nanoseconds. - Weight::from_ref_time(55_654_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 53_505 nanoseconds. + Weight::from_ref_time(53_954_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda DecidingCount (r:1 w:0) // Storage: Referenda TrackQueue (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:0) fn nudge_referendum_queued() -> Weight { - // Minimum execution time: 56_264 nanoseconds. - Weight::from_ref_time(57_243_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 55_473 nanoseconds. + Weight::from_ref_time(56_134_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda DecidingCount (r:1 w:0) // Storage: Referenda TrackQueue (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:0) fn nudge_referendum_not_queued() -> Weight { - // Minimum execution time: 56_176 nanoseconds. - Weight::from_ref_time(56_931_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 55_330 nanoseconds. + Weight::from_ref_time(56_137_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_no_deposit() -> Weight { - // Minimum execution time: 28_851 nanoseconds. - Weight::from_ref_time(29_181_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 29_234 nanoseconds. + Weight::from_ref_time(30_016_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_preparing() -> Weight { - // Minimum execution time: 29_924 nanoseconds. - Weight::from_ref_time(30_481_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 30_320 nanoseconds. + Weight::from_ref_time(31_207_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) fn nudge_referendum_timed_out() -> Weight { - // Minimum execution time: 21_555 nanoseconds. - Weight::from_ref_time(22_338_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 22_278 nanoseconds. + Weight::from_ref_time(22_963_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_begin_deciding_failing() -> Weight { - // Minimum execution time: 40_675 nanoseconds. - Weight::from_ref_time(41_190_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 42_438 nanoseconds. + Weight::from_ref_time(43_206_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) // Storage: Referenda DecidingCount (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_begin_deciding_passing() -> Weight { - // Minimum execution time: 42_598 nanoseconds. - Weight::from_ref_time(43_416_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 44_071 nanoseconds. + Weight::from_ref_time(44_793_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_begin_confirming() -> Weight { - // Minimum execution time: 38_642 nanoseconds. - Weight::from_ref_time(39_467_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_206 nanoseconds. + Weight::from_ref_time(41_719_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_end_confirming() -> Weight { - // Minimum execution time: 40_249 nanoseconds. - Weight::from_ref_time(41_288_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 41_848 nanoseconds. + Weight::from_ref_time(42_645_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_continue_not_confirming() -> Weight { - // Minimum execution time: 36_822 nanoseconds. - Weight::from_ref_time(38_169_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 38_801 nanoseconds. + Weight::from_ref_time(39_701_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_continue_confirming() -> Weight { - // Minimum execution time: 36_981 nanoseconds. - Weight::from_ref_time(37_999_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 37_936 nanoseconds. + Weight::from_ref_time(38_758_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:2 w:2) // Storage: Scheduler Lookup (r:1 w:1) fn nudge_referendum_approved() -> Weight { - // Minimum execution time: 48_632 nanoseconds. - Weight::from_ref_time(50_397_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 50_402 nanoseconds. + Weight::from_ref_time(51_317_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Referenda ReferendumInfoFor (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:0) // Storage: Scheduler Agenda (r:1 w:1) fn nudge_referendum_rejected() -> Weight { - // Minimum execution time: 38_784 nanoseconds. - Weight::from_ref_time(39_377_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_386 nanoseconds. + Weight::from_ref_time(41_208_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/kusama/src/weights/pallet_scheduler.rs b/runtime/kusama/src/weights/pallet_scheduler.rs index b1bf4322bc1e..996812108490 100644 --- a/runtime/kusama/src/weights/pallet_scheduler.rs +++ b/runtime/kusama/src/weights/pallet_scheduler.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_scheduler` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -46,95 +46,95 @@ pub struct WeightInfo(PhantomData); impl pallet_scheduler::WeightInfo for WeightInfo { // Storage: Scheduler IncompleteSince (r:1 w:1) fn service_agendas_base() -> Weight { - // Minimum execution time: 4_349 nanoseconds. - Weight::from_ref_time(4_501_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_209 nanoseconds. + Weight::from_ref_time(5_314_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 50]`. fn service_agenda_base(s: u32, ) -> Weight { - // Minimum execution time: 3_640 nanoseconds. - Weight::from_ref_time(7_035_134 as u64) - // Standard Error: 1_932 - .saturating_add(Weight::from_ref_time(580_489 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_422 nanoseconds. + Weight::from_ref_time(7_634_599) + // Standard Error: 1_898 + .saturating_add(Weight::from_ref_time(568_946).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } fn service_task_base() -> Weight { - // Minimum execution time: 9_361 nanoseconds. - Weight::from_ref_time(9_558_000 as u64) + // Minimum execution time: 10_347 nanoseconds. + Weight::from_ref_time(10_527_000) } // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) /// The range of component `s` is `[128, 4194304]`. fn service_task_fetched(s: u32, ) -> Weight { - // Minimum execution time: 19_984 nanoseconds. - Weight::from_ref_time(20_103_000 as u64) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(1_284 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 22_214 nanoseconds. + Weight::from_ref_time(22_467_000) + // Standard Error: 1 + .saturating_add(Weight::from_ref_time(1_249).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:0 w:1) fn service_task_named() -> Weight { - // Minimum execution time: 10_456 nanoseconds. - Weight::from_ref_time(10_829_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_917 nanoseconds. + Weight::from_ref_time(12_096_000) + .saturating_add(T::DbWeight::get().writes(1)) } fn service_task_periodic() -> Weight { - // Minimum execution time: 9_309 nanoseconds. - Weight::from_ref_time(9_674_000 as u64) + // Minimum execution time: 10_323 nanoseconds. + Weight::from_ref_time(10_483_000) } fn execute_dispatch_signed() -> Weight { - // Minimum execution time: 3_707 nanoseconds. - Weight::from_ref_time(3_887_000 as u64) + // Minimum execution time: 4_174 nanoseconds. + Weight::from_ref_time(4_223_000) } fn execute_dispatch_unsigned() -> Weight { - // Minimum execution time: 3_719 nanoseconds. - Weight::from_ref_time(3_822_000 as u64) + // Minimum execution time: 4_299 nanoseconds. + Weight::from_ref_time(4_409_000) } // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 49]`. fn schedule(s: u32, ) -> Weight { - // Minimum execution time: 15_995 nanoseconds. - Weight::from_ref_time(21_056_607 as u64) - // Standard Error: 2_901 - .saturating_add(Weight::from_ref_time(610_726 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 18_532 nanoseconds. + Weight::from_ref_time(22_723_245) + // Standard Error: 3_361 + .saturating_add(Weight::from_ref_time(587_560).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) // Storage: Scheduler Lookup (r:0 w:1) /// The range of component `s` is `[1, 50]`. fn cancel(s: u32, ) -> Weight { - // Minimum execution time: 19_043 nanoseconds. - Weight::from_ref_time(21_275_923 as u64) - // Standard Error: 2_470 - .saturating_add(Weight::from_ref_time(599_926 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 21_473 nanoseconds. + Weight::from_ref_time(23_228_996) + // Standard Error: 1_918 + .saturating_add(Weight::from_ref_time(571_552).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 49]`. fn schedule_named(s: u32, ) -> Weight { - // Minimum execution time: 19_152 nanoseconds. - Weight::from_ref_time(24_767_793 as u64) - // Standard Error: 3_638 - .saturating_add(Weight::from_ref_time(618_722 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 21_893 nanoseconds. + Weight::from_ref_time(26_544_205) + // Standard Error: 3_088 + .saturating_add(Weight::from_ref_time(606_697).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[1, 50]`. fn cancel_named(s: u32, ) -> Weight { - // Minimum execution time: 20_512 nanoseconds. - Weight::from_ref_time(22_833_394 as u64) - // Standard Error: 2_323 - .saturating_add(Weight::from_ref_time(620_445 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 22_972 nanoseconds. + Weight::from_ref_time(24_967_033) + // Standard Error: 1_912 + .saturating_add(Weight::from_ref_time(592_873).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/kusama/src/weights/pallet_session.rs b/runtime/kusama/src/weights/pallet_session.rs index 2ff4766f160e..c01e624f7bb9 100644 --- a/runtime/kusama/src/weights/pallet_session.rs +++ b/runtime/kusama/src/weights/pallet_session.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_session` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -48,18 +48,18 @@ impl pallet_session::WeightInfo for WeightInfo { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:6 w:6) fn set_keys() -> Weight { - // Minimum execution time: 49_769 nanoseconds. - Weight::from_ref_time(51_736_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 52_734 nanoseconds. + Weight::from_ref_time(55_029_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:0 w:6) fn purge_keys() -> Weight { - // Minimum execution time: 37_515 nanoseconds. - Weight::from_ref_time(38_874_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 40_087 nanoseconds. + Weight::from_ref_time(41_190_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(7)) } } diff --git a/runtime/kusama/src/weights/pallet_staking.rs b/runtime/kusama/src/weights/pallet_staking.rs index 608eedb79262..8159b08e794d 100644 --- a/runtime/kusama/src/weights/pallet_staking.rs +++ b/runtime/kusama/src/weights/pallet_staking.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_staking` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -50,10 +50,10 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - // Minimum execution time: 43_104 nanoseconds. - Weight::from_ref_time(44_132_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 48_252 nanoseconds. + Weight::from_ref_time(48_821_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) @@ -61,10 +61,10 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra() -> Weight { - // Minimum execution time: 79_519 nanoseconds. - Weight::from_ref_time(80_713_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 85_499 nanoseconds. + Weight::from_ref_time(86_732_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Nominators (r:1 w:0) @@ -76,10 +76,10 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListBags (r:2 w:2) fn unbond() -> Weight { - // Minimum execution time: 86_781 nanoseconds. - Weight::from_ref_time(87_699_000 as u64) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 92_417 nanoseconds. + Weight::from_ref_time(95_427_000) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) @@ -87,12 +87,12 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 38_383 nanoseconds. - Weight::from_ref_time(40_391_884 as u64) - // Standard Error: 1_926 - .saturating_add(Weight::from_ref_time(13_869 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 41_289 nanoseconds. + Weight::from_ref_time(42_612_758) + // Standard Error: 799 + .saturating_add(Weight::from_ref_time(16_044).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) @@ -107,14 +107,16 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { - // Minimum execution time: 72_726 nanoseconds. - Weight::from_ref_time(74_449_922 as u64) - // Standard Error: 1_212 - .saturating_add(Weight::from_ref_time(2_788 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(11 as u64)) + // Minimum execution time: 80_967 nanoseconds. + Weight::from_ref_time(85_727_324) + // Standard Error: 3_358 + .saturating_add(Weight::from_ref_time(942_386).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(12)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinValidatorBond (r:1 w:0) @@ -128,22 +130,22 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - // Minimum execution time: 58_309 nanoseconds. - Weight::from_ref_time(59_475_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 63_528 nanoseconds. + Weight::from_ref_time(63_877_000) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { - // Minimum execution time: 33_254 nanoseconds. - Weight::from_ref_time(29_388_895 as u64) - // Standard Error: 11_549 - .saturating_add(Weight::from_ref_time(6_414_781 as u64).saturating_mul(k as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(k as u64))) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(k as u64))) + // Minimum execution time: 35_580 nanoseconds. + Weight::from_ref_time(30_905_568) + // Standard Error: 11_627 + .saturating_add(Weight::from_ref_time(6_865_919).saturating_mul(k.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinNominatorBond (r:1 w:0) @@ -158,13 +160,13 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 24]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 60_454 nanoseconds. - Weight::from_ref_time(59_639_286 as u64) - // Standard Error: 7_738 - .saturating_add(Weight::from_ref_time(2_394_179 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 65_776 nanoseconds. + Weight::from_ref_time(64_676_849) + // Standard Error: 9_041 + .saturating_add(Weight::from_ref_time(2_639_322).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Validators (r:1 w:0) @@ -174,59 +176,59 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Minimum execution time: 56_822 nanoseconds. - Weight::from_ref_time(57_376_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 61_209 nanoseconds. + Weight::from_ref_time(61_822_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - // Minimum execution time: 14_896 nanoseconds. - Weight::from_ref_time(15_201_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 16_015 nanoseconds. + Weight::from_ref_time(16_273_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - // Minimum execution time: 22_255 nanoseconds. - Weight::from_ref_time(22_833_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 23_786 nanoseconds. + Weight::from_ref_time(24_182_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - // Minimum execution time: 3_940 nanoseconds. - Weight::from_ref_time(4_374_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_270 nanoseconds. + Weight::from_ref_time(4_433_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - // Minimum execution time: 3_897 nanoseconds. - Weight::from_ref_time(4_113_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_510 nanoseconds. + Weight::from_ref_time(4_667_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - // Minimum execution time: 3_954 nanoseconds. - Weight::from_ref_time(4_130_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_505 nanoseconds. + Weight::from_ref_time(4_702_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - // Minimum execution time: 3_944 nanoseconds. - Weight::from_ref_time(4_107_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_513 nanoseconds. + Weight::from_ref_time(4_669_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Invulnerables (r:0 w:1) /// The range of component `v` is `[0, 1000]`. fn set_invulnerables(v: u32, ) -> Weight { - // Minimum execution time: 4_262 nanoseconds. - Weight::from_ref_time(4_644_196 as u64) - // Standard Error: 29 - .saturating_add(Weight::from_ref_time(10_165 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_598 nanoseconds. + Weight::from_ref_time(5_133_518) + // Standard Error: 33 + .saturating_add(Weight::from_ref_time(10_439).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking SlashingSpans (r:1 w:0) @@ -243,23 +245,23 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { - // Minimum execution time: 69_465 nanoseconds. - Weight::from_ref_time(72_255_081 as u64) - // Standard Error: 2_127 - .saturating_add(Weight::from_ref_time(868_173 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 74_643 nanoseconds. + Weight::from_ref_time(79_489_383) + // Standard Error: 2_208 + .saturating_add(Weight::from_ref_time(930_546).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(12)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: Staking UnappliedSlashes (r:1 w:1) /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { - // Minimum execution time: 119_457 nanoseconds. - Weight::from_ref_time(1_336_120_543 as u64) - // Standard Error: 87_691 - .saturating_add(Weight::from_ref_time(7_429_607 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 120_224 nanoseconds. + Weight::from_ref_time(1_322_684_147) + // Standard Error: 86_380 + .saturating_add(Weight::from_ref_time(7_464_294).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking ErasValidatorReward (r:1 w:0) @@ -270,16 +272,16 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking ErasValidatorPrefs (r:1 w:0) // Storage: Staking Payee (r:1 w:0) // Storage: System Account (r:1 w:1) - /// The range of component `n` is `[0, 256]`. + /// The range of component `n` is `[0, 512]`. fn payout_stakers_dead_controller(n: u32, ) -> Weight { - // Minimum execution time: 92_948 nanoseconds. - Weight::from_ref_time(130_397_907 as u64) - // Standard Error: 14_923 - .saturating_add(Weight::from_ref_time(19_907_210 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(n as u64))) + // Minimum execution time: 111_668 nanoseconds. + Weight::from_ref_time(225_472_933) + // Standard Error: 16_133 + .saturating_add(Weight::from_ref_time(21_946_787).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) } // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking ErasValidatorReward (r:1 w:0) @@ -291,16 +293,16 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking Payee (r:1 w:0) // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - /// The range of component `n` is `[0, 256]`. + /// The range of component `n` is `[0, 512]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { - // Minimum execution time: 108_497 nanoseconds. - Weight::from_ref_time(162_756_589 as u64) - // Standard Error: 30_079 - .saturating_add(Weight::from_ref_time(27_543_828 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(n as u64))) + // Minimum execution time: 129_291 nanoseconds. + Weight::from_ref_time(76_271_315) + // Standard Error: 103_238 + .saturating_add(Weight::from_ref_time(32_669_236).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -310,12 +312,12 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListBags (r:2 w:2) /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { - // Minimum execution time: 78_279 nanoseconds. - Weight::from_ref_time(80_070_464 as u64) - // Standard Error: 4_979 - .saturating_add(Weight::from_ref_time(49_821 as u64).saturating_mul(l as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 85_340 nanoseconds. + Weight::from_ref_time(87_202_743) + // Standard Error: 4_832 + .saturating_add(Weight::from_ref_time(47_309).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: System Account (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) @@ -332,17 +334,16 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking SpanSlash (r:0 w:1) /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { - // Minimum execution time: 77_611 nanoseconds. - Weight::from_ref_time(79_448_315 as u64) - // Standard Error: 2_582 - .saturating_add(Weight::from_ref_time(862_567 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 85_440 nanoseconds. + Weight::from_ref_time(87_846_380) + // Standard Error: 2_098 + .saturating_add(Weight::from_ref_time(914_598).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(12)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: Staking SlashingSpans (r:1 w:0) - // Storage: VoterList ListBags (r:183 w:0) + // Storage: VoterList ListBags (r:166 w:0) // Storage: VoterList ListNodes (r:101 w:0) // Storage: Staking Nominators (r:101 w:0) // Storage: Staking Validators (r:2 w:0) @@ -358,58 +359,57 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking ErasStakers (r:0 w:1) // Storage: Staking ErasTotalStake (r:0 w:1) // Storage: Staking ErasStartSessionIndex (r:0 w:1) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[1, 10]`. /// The range of component `n` is `[0, 100]`. fn new_era(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 441_741 nanoseconds. - Weight::from_ref_time(444_325_000 as u64) - // Standard Error: 1_735_478 - .saturating_add(Weight::from_ref_time(58_700_922 as u64).saturating_mul(v as u64)) - // Standard Error: 172_930 - .saturating_add(Weight::from_ref_time(12_724_841 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(191 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(v as u64))) + // Minimum execution time: 442_830 nanoseconds. + Weight::from_ref_time(444_568_000) + // Standard Error: 1_789_238 + .saturating_add(Weight::from_ref_time(58_626_494).saturating_mul(v.into())) + // Standard Error: 178_287 + .saturating_add(Weight::from_ref_time(13_398_253).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(173)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) } // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: Staking SlashingSpans (r:21 w:0) - // Storage: VoterList ListBags (r:183 w:0) + // Storage: VoterList ListBags (r:166 w:0) // Storage: VoterList ListNodes (r:1500 w:0) // Storage: Staking Nominators (r:1500 w:0) // Storage: Staking Validators (r:500 w:0) // Storage: Staking Bonded (r:1500 w:0) // Storage: Staking Ledger (r:1500 w:0) // Storage: System BlockWeight (r:1 w:1) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[500, 1000]`. /// The range of component `n` is `[500, 1000]`. - /// The range of component `s` is `[1, 20]`. - fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { - // Minimum execution time: 25_700_092 nanoseconds. - Weight::from_ref_time(25_792_272_000 as u64) - // Standard Error: 477_913 - .saturating_add(Weight::from_ref_time(11_545_647 as u64).saturating_mul(v as u64)) - // Standard Error: 477_913 - .saturating_add(Weight::from_ref_time(11_116_420 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(186 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + fn get_npos_voters(v: u32, n: u32, ) -> Weight { + // Minimum execution time: 26_020_599 nanoseconds. + Weight::from_ref_time(26_116_645_000) + // Standard Error: 592_800 + .saturating_add(Weight::from_ref_time(5_010_057).saturating_mul(v.into())) + // Standard Error: 592_800 + .saturating_add(Weight::from_ref_time(5_293_778).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(168)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Staking CounterForValidators (r:1 w:0) // Storage: Staking Validators (r:501 w:0) // Storage: System BlockWeight (r:1 w:1) /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { - // Minimum execution time: 3_338_127 nanoseconds. - Weight::from_ref_time(3_386_919_000 as u64) - // Standard Error: 39_447 - .saturating_add(Weight::from_ref_time(2_627_920 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 3_671_302 nanoseconds. + Weight::from_ref_time(22_270_134) + // Standard Error: 31_742 + .saturating_add(Weight::from_ref_time(7_565_964).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking MinCommission (r:0 w:1) // Storage: Staking MinValidatorBond (r:0 w:1) @@ -418,9 +418,9 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_set() -> Weight { - // Minimum execution time: 7_335 nanoseconds. - Weight::from_ref_time(7_692_000 as u64) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 7_726 nanoseconds. + Weight::from_ref_time(8_054_000) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:0 w:1) // Storage: Staking MinValidatorBond (r:0 w:1) @@ -429,9 +429,9 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_remove() -> Weight { - // Minimum execution time: 6_297 nanoseconds. - Weight::from_ref_time(6_555_000 as u64) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 7_325 nanoseconds. + Weight::from_ref_time(7_532_000) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -444,17 +444,17 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - // Minimum execution time: 65_691 nanoseconds. - Weight::from_ref_time(66_805_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 71_895 nanoseconds. + Weight::from_ref_time(73_682_000) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:1 w:0) // Storage: Staking Validators (r:1 w:1) fn force_apply_min_commission() -> Weight { - // Minimum execution time: 14_328 nanoseconds. - Weight::from_ref_time(14_698_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_463 nanoseconds. + Weight::from_ref_time(15_679_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/pallet_timestamp.rs b/runtime/kusama/src/weights/pallet_timestamp.rs index a8fec2a86353..1b4f7ff3e11c 100644 --- a/runtime/kusama/src/weights/pallet_timestamp.rs +++ b/runtime/kusama/src/weights/pallet_timestamp.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_timestamp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -47,13 +47,13 @@ impl pallet_timestamp::WeightInfo for WeightInfo { // Storage: Timestamp Now (r:1 w:1) // Storage: Babe CurrentSlot (r:1 w:0) fn set() -> Weight { - // Minimum execution time: 9_131 nanoseconds. - Weight::from_ref_time(9_364_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_039 nanoseconds. + Weight::from_ref_time(10_371_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } fn on_finalize() -> Weight { - // Minimum execution time: 3_891 nanoseconds. - Weight::from_ref_time(4_039_000 as u64) + // Minimum execution time: 4_231 nanoseconds. + Weight::from_ref_time(4_282_000) } } diff --git a/runtime/kusama/src/weights/pallet_tips.rs b/runtime/kusama/src/weights/pallet_tips.rs index 76a83f8d482c..64f1eed842f6 100644 --- a/runtime/kusama/src/weights/pallet_tips.rs +++ b/runtime/kusama/src/weights/pallet_tips.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_tips` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -48,20 +48,20 @@ impl pallet_tips::WeightInfo for WeightInfo { // Storage: Tips Tips (r:1 w:1) /// The range of component `r` is `[0, 16384]`. fn report_awesome(r: u32, ) -> Weight { - // Minimum execution time: 28_001 nanoseconds. - Weight::from_ref_time(29_838_155 as u64) - // Standard Error: 5 - .saturating_add(Weight::from_ref_time(1_786 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 31_356 nanoseconds. + Weight::from_ref_time(32_173_893) + // Standard Error: 6 + .saturating_add(Weight::from_ref_time(1_836).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) fn retract_tip() -> Weight { - // Minimum execution time: 28_123 nanoseconds. - Weight::from_ref_time(28_778_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 29_649 nanoseconds. + Weight::from_ref_time(30_195_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Members (r:1 w:0) // Storage: Tips Reasons (r:1 w:1) @@ -69,25 +69,25 @@ impl pallet_tips::WeightInfo for WeightInfo { /// The range of component `r` is `[0, 16384]`. /// The range of component `t` is `[1, 19]`. fn tip_new(r: u32, t: u32, ) -> Weight { - // Minimum execution time: 21_821 nanoseconds. - Weight::from_ref_time(18_615_217 as u64) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(1_707 as u64).saturating_mul(r as u64)) - // Standard Error: 5_686 - .saturating_add(Weight::from_ref_time(246_831 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 23_780 nanoseconds. + Weight::from_ref_time(21_934_867) + // Standard Error: 8 + .saturating_add(Weight::from_ref_time(1_698).saturating_mul(r.into())) + // Standard Error: 7_264 + .saturating_add(Weight::from_ref_time(202_703).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Members (r:1 w:0) // Storage: Tips Tips (r:1 w:1) /// The range of component `t` is `[1, 19]`. fn tip(t: u32, ) -> Weight { - // Minimum execution time: 14_824 nanoseconds. - Weight::from_ref_time(15_649_583 as u64) - // Standard Error: 2_623 - .saturating_add(Weight::from_ref_time(79_250 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_512 nanoseconds. + Weight::from_ref_time(16_156_911) + // Standard Error: 1_681 + .saturating_add(Weight::from_ref_time(152_863).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Tips Tips (r:1 w:1) // Storage: PhragmenElection Members (r:1 w:0) @@ -95,22 +95,22 @@ impl pallet_tips::WeightInfo for WeightInfo { // Storage: Tips Reasons (r:0 w:1) /// The range of component `t` is `[1, 19]`. fn close_tip(t: u32, ) -> Weight { - // Minimum execution time: 43_497 nanoseconds. - Weight::from_ref_time(45_852_110 as u64) - // Standard Error: 9_116 - .saturating_add(Weight::from_ref_time(107_417 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 46_967 nanoseconds. + Weight::from_ref_time(48_723_449) + // Standard Error: 5_023 + .saturating_add(Weight::from_ref_time(141_125).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) /// The range of component `t` is `[1, 19]`. fn slash_tip(t: u32, ) -> Weight { - // Minimum execution time: 18_025 nanoseconds. - Weight::from_ref_time(18_866_498 as u64) - // Standard Error: 1_476 - .saturating_add(Weight::from_ref_time(49_648 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 19_819 nanoseconds. + Weight::from_ref_time(20_688_146) + // Standard Error: 1_508 + .saturating_add(Weight::from_ref_time(37_815).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/kusama/src/weights/pallet_treasury.rs b/runtime/kusama/src/weights/pallet_treasury.rs index a64f02def78e..643bd4caa6bf 100644 --- a/runtime/kusama/src/weights/pallet_treasury.rs +++ b/runtime/kusama/src/weights/pallet_treasury.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_treasury` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -48,58 +48,60 @@ impl pallet_treasury::WeightInfo for WeightInfo { // Storage: Treasury Approvals (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn spend() -> Weight { - // Minimum execution time: 18_027 nanoseconds. - Weight::from_ref_time(18_673_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 18_940 nanoseconds. + Weight::from_ref_time(19_320_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - // Minimum execution time: 26_125 nanoseconds. - Weight::from_ref_time(26_944_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 27_243 nanoseconds. + Weight::from_ref_time(27_811_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:1 w:1) fn reject_proposal() -> Weight { - // Minimum execution time: 36_779 nanoseconds. - Weight::from_ref_time(37_555_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_424 nanoseconds. + Weight::from_ref_time(41_008_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) /// The range of component `p` is `[0, 99]`. fn approve_proposal(p: u32, ) -> Weight { - // Minimum execution time: 9_601 nanoseconds. - Weight::from_ref_time(12_969_695 as u64) - // Standard Error: 1_086 - .saturating_add(Weight::from_ref_time(48_117 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_590 nanoseconds. + Weight::from_ref_time(13_920_232) + // Standard Error: 1_091 + .saturating_add(Weight::from_ref_time(48_304).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) fn remove_approval() -> Weight { - // Minimum execution time: 7_382 nanoseconds. - Weight::from_ref_time(7_715_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_481 nanoseconds. + Weight::from_ref_time(8_677_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } + // Storage: Treasury Inactive (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: Treasury Approvals (r:1 w:1) // Storage: Bounties BountyApprovals (r:1 w:1) // Storage: System Account (r:1 w:1) // Storage: Treasury Proposals (r:2 w:2) /// The range of component `p` is `[0, 100]`. fn on_initialize_proposals(p: u32, ) -> Weight { - // Minimum execution time: 48_096 nanoseconds. - Weight::from_ref_time(53_729_903 as u64) - // Standard Error: 26_120 - .saturating_add(Weight::from_ref_time(24_134_288 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(p as u64))) + // Minimum execution time: 54_749 nanoseconds. + Weight::from_ref_time(66_521_982) + // Standard Error: 46_495 + .saturating_add(Weight::from_ref_time(25_094_728).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(5)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(p.into()))) } } diff --git a/runtime/kusama/src/weights/pallet_utility.rs b/runtime/kusama/src/weights/pallet_utility.rs index 639c99640f60..de35d4d41b06 100644 --- a/runtime/kusama/src/weights/pallet_utility.rs +++ b/runtime/kusama/src/weights/pallet_utility.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_utility` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -46,31 +46,31 @@ pub struct WeightInfo(PhantomData); impl pallet_utility::WeightInfo for WeightInfo { /// The range of component `c` is `[0, 1000]`. fn batch(c: u32, ) -> Weight { - // Minimum execution time: 11_138 nanoseconds. - Weight::from_ref_time(15_220_146 as u64) - // Standard Error: 2_737 - .saturating_add(Weight::from_ref_time(3_434_990 as u64).saturating_mul(c as u64)) + // Minimum execution time: 11_828 nanoseconds. + Weight::from_ref_time(13_760_762) + // Standard Error: 2_491 + .saturating_add(Weight::from_ref_time(3_519_460).saturating_mul(c.into())) } fn as_derivative() -> Weight { - // Minimum execution time: 5_429 nanoseconds. - Weight::from_ref_time(5_578_000 as u64) + // Minimum execution time: 5_883 nanoseconds. + Weight::from_ref_time(6_003_000) } /// The range of component `c` is `[0, 1000]`. fn batch_all(c: u32, ) -> Weight { - // Minimum execution time: 11_082 nanoseconds. - Weight::from_ref_time(20_839_520 as u64) - // Standard Error: 2_688 - .saturating_add(Weight::from_ref_time(3_559_955 as u64).saturating_mul(c as u64)) + // Minimum execution time: 11_699 nanoseconds. + Weight::from_ref_time(18_867_729) + // Standard Error: 2_787 + .saturating_add(Weight::from_ref_time(3_685_749).saturating_mul(c.into())) } fn dispatch_as() -> Weight { - // Minimum execution time: 13_275 nanoseconds. - Weight::from_ref_time(13_601_000 as u64) + // Minimum execution time: 13_869 nanoseconds. + Weight::from_ref_time(14_444_000) } /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { - // Minimum execution time: 11_090 nanoseconds. - Weight::from_ref_time(14_265_371 as u64) - // Standard Error: 2_953 - .saturating_add(Weight::from_ref_time(3_419_726 as u64).saturating_mul(c as u64)) + // Minimum execution time: 12_089 nanoseconds. + Weight::from_ref_time(14_362_564) + // Standard Error: 2_587 + .saturating_add(Weight::from_ref_time(3_511_549).saturating_mul(c.into())) } } diff --git a/runtime/kusama/src/weights/pallet_vesting.rs b/runtime/kusama/src/weights/pallet_vesting.rs index b447032df4a7..b1973ae560f3 100644 --- a/runtime/kusama/src/weights/pallet_vesting.rs +++ b/runtime/kusama/src/weights/pallet_vesting.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_vesting` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -49,28 +49,28 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_locked(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 36_840 nanoseconds. - Weight::from_ref_time(36_369_202 as u64) - // Standard Error: 1_658 - .saturating_add(Weight::from_ref_time(44_590 as u64).saturating_mul(l as u64)) - // Standard Error: 2_951 - .saturating_add(Weight::from_ref_time(63_226 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 39_622 nanoseconds. + Weight::from_ref_time(38_665_613) + // Standard Error: 1_455 + .saturating_add(Weight::from_ref_time(51_628).saturating_mul(l.into())) + // Standard Error: 2_589 + .saturating_add(Weight::from_ref_time(69_995).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_unlocked(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 36_868 nanoseconds. - Weight::from_ref_time(36_145_466 as u64) - // Standard Error: 1_169 - .saturating_add(Weight::from_ref_time(35_637 as u64).saturating_mul(l as u64)) - // Standard Error: 2_080 - .saturating_add(Weight::from_ref_time(55_928 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 39_308 nanoseconds. + Weight::from_ref_time(39_048_399) + // Standard Error: 1_505 + .saturating_add(Weight::from_ref_time(40_782).saturating_mul(l.into())) + // Standard Error: 2_678 + .saturating_add(Weight::from_ref_time(49_990).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -78,14 +78,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 36_351 nanoseconds. - Weight::from_ref_time(35_746_232 as u64) - // Standard Error: 1_101 - .saturating_add(Weight::from_ref_time(45_710 as u64).saturating_mul(l as u64)) - // Standard Error: 1_959 - .saturating_add(Weight::from_ref_time(75_325 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 39_694 nanoseconds. + Weight::from_ref_time(39_083_772) + // Standard Error: 1_067 + .saturating_add(Weight::from_ref_time(42_411).saturating_mul(l.into())) + // Standard Error: 1_898 + .saturating_add(Weight::from_ref_time(62_435).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -93,14 +93,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 36_232 nanoseconds. - Weight::from_ref_time(36_409_437 as u64) - // Standard Error: 1_344 - .saturating_add(Weight::from_ref_time(22_680 as u64).saturating_mul(l as u64)) - // Standard Error: 2_391 - .saturating_add(Weight::from_ref_time(53_105 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 39_075 nanoseconds. + Weight::from_ref_time(38_768_631) + // Standard Error: 1_472 + .saturating_add(Weight::from_ref_time(43_764).saturating_mul(l.into())) + // Standard Error: 2_620 + .saturating_add(Weight::from_ref_time(48_362).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:1 w:1) @@ -108,14 +108,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[0, 27]`. fn vested_transfer(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 50_119 nanoseconds. - Weight::from_ref_time(50_184_800 as u64) - // Standard Error: 2_011 - .saturating_add(Weight::from_ref_time(39_460 as u64).saturating_mul(l as u64)) - // Standard Error: 3_579 - .saturating_add(Weight::from_ref_time(51_047 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 54_424 nanoseconds. + Weight::from_ref_time(54_994_619) + // Standard Error: 2_205 + .saturating_add(Weight::from_ref_time(28_932).saturating_mul(l.into())) + // Standard Error: 3_923 + .saturating_add(Weight::from_ref_time(26_321).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:2 w:2) @@ -123,14 +123,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 49_510 nanoseconds. - Weight::from_ref_time(49_839_835 as u64) - // Standard Error: 1_678 - .saturating_add(Weight::from_ref_time(39_770 as u64).saturating_mul(l as u64)) - // Standard Error: 2_985 - .saturating_add(Weight::from_ref_time(33_950 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 52_823 nanoseconds. + Weight::from_ref_time(53_657_670) + // Standard Error: 2_072 + .saturating_add(Weight::from_ref_time(41_992).saturating_mul(l.into())) + // Standard Error: 3_687 + .saturating_add(Weight::from_ref_time(29_368).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -138,14 +138,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 38_167 nanoseconds. - Weight::from_ref_time(37_606_228 as u64) - // Standard Error: 1_669 - .saturating_add(Weight::from_ref_time(47_567 as u64).saturating_mul(l as u64)) - // Standard Error: 3_083 - .saturating_add(Weight::from_ref_time(48_620 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 40_578 nanoseconds. + Weight::from_ref_time(40_035_118) + // Standard Error: 1_209 + .saturating_add(Weight::from_ref_time(47_771).saturating_mul(l.into())) + // Standard Error: 2_233 + .saturating_add(Weight::from_ref_time(71_486).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -153,13 +153,13 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 37_719 nanoseconds. - Weight::from_ref_time(36_893_012 as u64) - // Standard Error: 886 - .saturating_add(Weight::from_ref_time(45_584 as u64).saturating_mul(l as u64)) - // Standard Error: 1_636 - .saturating_add(Weight::from_ref_time(71_780 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 40_822 nanoseconds. + Weight::from_ref_time(40_597_541) + // Standard Error: 1_111 + .saturating_add(Weight::from_ref_time(36_472).saturating_mul(l.into())) + // Standard Error: 2_053 + .saturating_add(Weight::from_ref_time(61_580).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/kusama/src/weights/pallet_whitelist.rs b/runtime/kusama/src/weights/pallet_whitelist.rs index 1d46a0cf278d..44720fea7011 100644 --- a/runtime/kusama/src/weights/pallet_whitelist.rs +++ b/runtime/kusama/src/weights/pallet_whitelist.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_whitelist` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -47,37 +47,40 @@ impl pallet_whitelist::WeightInfo for WeightInfo { // Storage: Whitelist WhitelistedCall (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn whitelist_call() -> Weight { - // Minimum execution time: 21_348 nanoseconds. - Weight::from_ref_time(21_955_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 23_640 nanoseconds. + Weight::from_ref_time(24_012_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Whitelist WhitelistedCall (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) fn remove_whitelisted_call() -> Weight { - // Minimum execution time: 20_057 nanoseconds. - Weight::from_ref_time(20_459_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 22_267 nanoseconds. + Weight::from_ref_time(22_799_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Whitelist WhitelistedCall (r:1 w:1) - // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:1 w:1) - fn dispatch_whitelisted_call() -> Weight { - // Minimum execution time: 5_241_064 nanoseconds. - Weight::from_ref_time(5_341_341_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Storage: Preimage StatusFor (r:1 w:1) + /// The range of component `n` is `[1, 4194294]`. + fn dispatch_whitelisted_call(n: u32, ) -> Weight { + // Minimum execution time: 33_179 nanoseconds. + Weight::from_ref_time(33_518_000) + // Standard Error: 3 + .saturating_add(Weight::from_ref_time(1_269).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Whitelist WhitelistedCall (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) /// The range of component `n` is `[1, 10000]`. fn dispatch_whitelisted_call_with_preimage(n: u32, ) -> Weight { - // Minimum execution time: 23_639 nanoseconds. - Weight::from_ref_time(24_381_717 as u64) - // Standard Error: 4 - .saturating_add(Weight::from_ref_time(1_552 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 25_924 nanoseconds. + Weight::from_ref_time(26_902_307) + // Standard Error: 5 + .saturating_add(Weight::from_ref_time(1_597).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/kusama/src/weights/runtime_common_auctions.rs b/runtime/kusama/src/weights/runtime_common_auctions.rs index ce19ebe29b85..5c3b62956fa5 100644 --- a/runtime/kusama/src/weights/runtime_common_auctions.rs +++ b/runtime/kusama/src/weights/runtime_common_auctions.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::auctions` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -47,10 +47,10 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Auctions AuctionInfo (r:1 w:1) // Storage: Auctions AuctionCounter (r:1 w:1) fn new_auction() -> Weight { - // Minimum execution time: 16_030 nanoseconds. - Weight::from_ref_time(16_442_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 17_615 nanoseconds. + Weight::from_ref_time(18_245_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Paras ParaLifecycles (r:1 w:0) // Storage: Auctions AuctionCounter (r:1 w:0) @@ -60,10 +60,10 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Auctions ReservedAmounts (r:2 w:2) // Storage: System Account (r:1 w:1) fn bid() -> Weight { - // Minimum execution time: 70_405 nanoseconds. - Weight::from_ref_time(71_429_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 74_152 nanoseconds. + Weight::from_ref_time(76_170_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Auctions AuctionInfo (r:1 w:1) // Storage: Babe NextRandomness (r:1 w:0) @@ -78,19 +78,19 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar Paras (r:1 w:1) fn on_initialize() -> Weight { - // Minimum execution time: 14_537_408 nanoseconds. - Weight::from_ref_time(14_840_472_000 as u64) - .saturating_add(T::DbWeight::get().reads(3688 as u64)) - .saturating_add(T::DbWeight::get().writes(3683 as u64)) + // Minimum execution time: 16_174_592 nanoseconds. + Weight::from_ref_time(16_598_727_000) + .saturating_add(T::DbWeight::get().reads(3688)) + .saturating_add(T::DbWeight::get().writes(3683)) } // Storage: Auctions ReservedAmounts (r:37 w:36) // Storage: System Account (r:36 w:36) // Storage: Auctions Winning (r:0 w:3600) // Storage: Auctions AuctionInfo (r:0 w:1) fn cancel_auction() -> Weight { - // Minimum execution time: 4_592_707 nanoseconds. - Weight::from_ref_time(4_691_301_000 as u64) - .saturating_add(T::DbWeight::get().reads(73 as u64)) - .saturating_add(T::DbWeight::get().writes(3673 as u64)) + // Minimum execution time: 4_612_473 nanoseconds. + Weight::from_ref_time(4_676_417_000) + .saturating_add(T::DbWeight::get().reads(73)) + .saturating_add(T::DbWeight::get().writes(3673)) } } diff --git a/runtime/kusama/src/weights/runtime_common_claims.rs b/runtime/kusama/src/weights/runtime_common_claims.rs index b1b8fc140d7e..a0b15fa6edbf 100644 --- a/runtime/kusama/src/weights/runtime_common_claims.rs +++ b/runtime/kusama/src/weights/runtime_common_claims.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::claims` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -52,20 +52,20 @@ impl runtime_common::claims::WeightInfo for WeightInfo< // Storage: System Account (r:1 w:0) // Storage: Balances Locks (r:1 w:1) fn claim() -> Weight { - // Minimum execution time: 142_908 nanoseconds. - Weight::from_ref_time(144_759_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 145_439 nanoseconds. + Weight::from_ref_time(149_015_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Claims Total (r:1 w:1) // Storage: Claims Vesting (r:0 w:1) // Storage: Claims Claims (r:0 w:1) // Storage: Claims Signing (r:0 w:1) fn mint_claim() -> Weight { - // Minimum execution time: 11_398 nanoseconds. - Weight::from_ref_time(11_589_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 11_829 nanoseconds. + Weight::from_ref_time(12_387_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Claims Claims (r:1 w:1) // Storage: Claims Signing (r:1 w:1) @@ -75,10 +75,10 @@ impl runtime_common::claims::WeightInfo for WeightInfo< // Storage: System Account (r:1 w:0) // Storage: Balances Locks (r:1 w:1) fn claim_attest() -> Weight { - // Minimum execution time: 145_042 nanoseconds. - Weight::from_ref_time(147_273_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 147_923 nanoseconds. + Weight::from_ref_time(150_511_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Claims Preclaims (r:1 w:1) // Storage: Claims Signing (r:1 w:1) @@ -89,19 +89,19 @@ impl runtime_common::claims::WeightInfo for WeightInfo< // Storage: System Account (r:1 w:0) // Storage: Balances Locks (r:1 w:1) fn attest() -> Weight { - // Minimum execution time: 66_318 nanoseconds. - Weight::from_ref_time(67_665_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 68_794 nanoseconds. + Weight::from_ref_time(70_811_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Claims Claims (r:1 w:2) // Storage: Claims Vesting (r:1 w:2) // Storage: Claims Signing (r:1 w:2) // Storage: Claims Preclaims (r:1 w:1) fn move_claim() -> Weight { - // Minimum execution time: 21_013 nanoseconds. - Weight::from_ref_time(21_745_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 21_916 nanoseconds. + Weight::from_ref_time(22_574_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(7)) } } diff --git a/runtime/kusama/src/weights/runtime_common_crowdloan.rs b/runtime/kusama/src/weights/runtime_common_crowdloan.rs index 6ccff4eeb214..ea807f176b95 100644 --- a/runtime/kusama/src/weights/runtime_common_crowdloan.rs +++ b/runtime/kusama/src/weights/runtime_common_crowdloan.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::crowdloan` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -49,75 +49,77 @@ impl runtime_common::crowdloan::WeightInfo for WeightIn // Storage: Paras ParaLifecycles (r:1 w:0) // Storage: Crowdloan NextFundIndex (r:1 w:1) fn create() -> Weight { - // Minimum execution time: 45_380 nanoseconds. - Weight::from_ref_time(47_704_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 50_146 nanoseconds. + Weight::from_ref_time(50_861_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: Slots Leases (r:1 w:0) // Storage: Auctions AuctionInfo (r:1 w:0) // Storage: System Account (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: Crowdloan EndingsCount (r:1 w:0) // Storage: Crowdloan NewRaise (r:1 w:1) // Storage: unknown [0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291] (r:1 w:1) fn contribute() -> Weight { - // Minimum execution time: 114_903 nanoseconds. - Weight::from_ref_time(116_612_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 122_214 nanoseconds. + Weight::from_ref_time(123_819_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: System Account (r:2 w:2) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: unknown [0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0] (r:1 w:1) fn withdraw() -> Weight { - // Minimum execution time: 53_804 nanoseconds. - Weight::from_ref_time(54_387_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 61_345 nanoseconds. + Weight::from_ref_time(62_912_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `k` is `[0, 1000]`. fn refund(k: u32, ) -> Weight { - // Minimum execution time: 47_160 nanoseconds. - Weight::from_ref_time(62_090_000 as u64) - // Standard Error: 13_181 - .saturating_add(Weight::from_ref_time(17_394_035 as u64).saturating_mul(k as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(k as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(k as u64))) + // Minimum execution time: 49_330 nanoseconds. + Weight::from_ref_time(63_972_000) + // Standard Error: 13_381 + .saturating_add(Weight::from_ref_time(19_330_640).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(3)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(k.into()))) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: System Account (r:1 w:1) fn dissolve() -> Weight { - // Minimum execution time: 35_082 nanoseconds. - Weight::from_ref_time(35_672_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 38_711 nanoseconds. + Weight::from_ref_time(39_968_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Crowdloan Funds (r:1 w:1) fn edit() -> Weight { - // Minimum execution time: 23_638 nanoseconds. - Weight::from_ref_time(24_680_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 27_042 nanoseconds. + Weight::from_ref_time(28_113_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Crowdloan Funds (r:1 w:0) // Storage: unknown [0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291] (r:1 w:1) fn add_memo() -> Weight { - // Minimum execution time: 31_235 nanoseconds. - Weight::from_ref_time(32_150_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 35_084 nanoseconds. + Weight::from_ref_time(36_107_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Crowdloan Funds (r:1 w:0) // Storage: Crowdloan NewRaise (r:1 w:1) fn poke() -> Weight { - // Minimum execution time: 24_980 nanoseconds. - Weight::from_ref_time(26_297_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 27_126 nanoseconds. + Weight::from_ref_time(28_344_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Auctions AuctionInfo (r:1 w:0) // Storage: Crowdloan EndingsCount (r:1 w:1) @@ -131,13 +133,13 @@ impl runtime_common::crowdloan::WeightInfo for WeightIn // Storage: System Account (r:2 w:2) /// The range of component `n` is `[2, 100]`. fn on_initialize(n: u32, ) -> Weight { - // Minimum execution time: 101_764 nanoseconds. - Weight::from_ref_time(14_626_691 as u64) - // Standard Error: 39_547 - .saturating_add(Weight::from_ref_time(39_618_827 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(n as u64))) + // Minimum execution time: 106_838 nanoseconds. + Weight::from_ref_time(13_240_511) + // Standard Error: 45_032 + .saturating_add(Weight::from_ref_time(41_814_335).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)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) } } diff --git a/runtime/kusama/src/weights/runtime_common_paras_registrar.rs b/runtime/kusama/src/weights/runtime_common_paras_registrar.rs index 371d40009737..34256714809f 100644 --- a/runtime/kusama/src/weights/runtime_common_paras_registrar.rs +++ b/runtime/kusama/src/weights/runtime_common_paras_registrar.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::paras_registrar` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -48,10 +48,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:0) fn reserve() -> Weight { - // Minimum execution time: 30_030 nanoseconds. - Weight::from_ref_time(30_491_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 32_645 nanoseconds. + Weight::from_ref_time(33_252_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -63,10 +63,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras CurrentCodeHash (r:0 w:1) // Storage: Paras UpcomingParasGenesis (r:0 w:1) fn register() -> Weight { - // Minimum execution time: 7_287_004 nanoseconds. - Weight::from_ref_time(7_413_198_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 7_441_785 nanoseconds. + Weight::from_ref_time(7_538_553_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -78,10 +78,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras CurrentCodeHash (r:0 w:1) // Storage: Paras UpcomingParasGenesis (r:0 w:1) fn force_register() -> Weight { - // Minimum execution time: 7_287_206 nanoseconds. - Weight::from_ref_time(7_394_740_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 7_402_898 nanoseconds. + Weight::from_ref_time(7_542_285_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -90,10 +90,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar PendingSwap (r:0 w:1) fn deregister() -> Weight { - // Minimum execution time: 47_643 nanoseconds. - Weight::from_ref_time(48_704_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 50_977 nanoseconds. + Weight::from_ref_time(52_477_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Registrar Paras (r:1 w:0) // Storage: Paras ParaLifecycles (r:2 w:2) @@ -103,10 +103,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Crowdloan Funds (r:2 w:2) // Storage: Slots Leases (r:2 w:2) fn swap() -> Weight { - // Minimum execution time: 42_640 nanoseconds. - Weight::from_ref_time(44_000_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 46_017 nanoseconds. + Weight::from_ref_time(47_627_000) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras FutureCodeHash (r:1 w:1) // Storage: Paras UpgradeRestrictionSignal (r:1 w:1) @@ -120,20 +120,20 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras FutureCodeUpgrades (r:0 w:1) /// The range of component `b` is `[1, 3145728]`. fn schedule_code_upgrade(b: u32, ) -> Weight { - // Minimum execution time: 41_757 nanoseconds. - Weight::from_ref_time(42_119_000 as u64) + // Minimum execution time: 43_949 nanoseconds. + Weight::from_ref_time(44_227_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_290 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + .saturating_add(Weight::from_ref_time(2_326).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras Heads (r:0 w:1) /// The range of component `b` is `[1, 1048576]`. fn set_current_head(b: u32, ) -> Weight { - // Minimum execution time: 12_623 nanoseconds. - Weight::from_ref_time(12_795_000 as u64) + // Minimum execution time: 13_993 nanoseconds. + Weight::from_ref_time(14_190_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(909 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(909).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/runtime_common_slots.rs b/runtime/kusama/src/weights/runtime_common_slots.rs index e085ebc165eb..d751d6387039 100644 --- a/runtime/kusama/src/weights/runtime_common_slots.rs +++ b/runtime/kusama/src/weights/runtime_common_slots.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::slots` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -47,40 +47,40 @@ impl runtime_common::slots::WeightInfo for WeightInfo Weight { - // Minimum execution time: 30_486 nanoseconds. - Weight::from_ref_time(31_175_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 33_382 nanoseconds. + Weight::from_ref_time(33_715_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Paras Parachains (r:1 w:0) // Storage: Slots Leases (r:101 w:100) - // Storage: Paras ParaLifecycles (r:101 w:101) + // Storage: Paras ParaLifecycles (r:100 w:100) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar Paras (r:100 w:100) - /// The range of component `c` is `[1, 100]`. - /// The range of component `t` is `[1, 100]`. + /// 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 { - // Minimum execution time: 546_918 nanoseconds. - Weight::from_ref_time(550_885_000 as u64) - // Standard Error: 71_051 - .saturating_add(Weight::from_ref_time(2_051_562 as u64).saturating_mul(c as u64)) - // Standard Error: 71_051 - .saturating_add(Weight::from_ref_time(11_603_107 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(t as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(t as u64))) + // Minimum execution time: 557_126 nanoseconds. + Weight::from_ref_time(563_537_000) + // Standard Error: 70_430 + .saturating_add(Weight::from_ref_time(2_305_346).saturating_mul(c.into())) + // Standard Error: 70_430 + .saturating_add(Weight::from_ref_time(12_575_762).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().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()))) } // Storage: Slots Leases (r:1 w:1) // Storage: System Account (r:8 w:8) fn clear_all_leases() -> Weight { - // Minimum execution time: 89_987 nanoseconds. - Weight::from_ref_time(91_954_000 as u64) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 96_232 nanoseconds. + Weight::from_ref_time(98_424_000) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(9)) } // Storage: Slots Leases (r:1 w:0) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -88,9 +88,9 @@ impl runtime_common::slots::WeightInfo for WeightInfo Weight { - // Minimum execution time: 28_117 nanoseconds. - Weight::from_ref_time(29_284_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 29_782 nanoseconds. + Weight::from_ref_time(30_661_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/kusama/src/weights/runtime_parachains_configuration.rs b/runtime/kusama/src/weights/runtime_parachains_configuration.rs index d8ca6f3c3700..078bd76a26f9 100644 --- a/runtime/kusama/src/weights/runtime_parachains_configuration.rs +++ b/runtime/kusama/src/weights/runtime_parachains_configuration.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::configuration` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -48,50 +48,50 @@ impl runtime_parachains::configuration::WeightInfo for // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_block_number() -> Weight { - // Minimum execution time: 11_808 nanoseconds. - Weight::from_ref_time(12_113_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_345 nanoseconds. + Weight::from_ref_time(12_862_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_u32() -> Weight { - // Minimum execution time: 11_818 nanoseconds. - Weight::from_ref_time(12_074_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_744 nanoseconds. + Weight::from_ref_time(13_172_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_option_u32() -> Weight { - // Minimum execution time: 11_703 nanoseconds. - Weight::from_ref_time(11_940_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_398 nanoseconds. + Weight::from_ref_time(12_888_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_weight() -> Weight { - // Minimum execution time: 11_865 nanoseconds. - Weight::from_ref_time(12_334_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_592 nanoseconds. + Weight::from_ref_time(13_133_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Benchmark Override (r:0 w:0) fn set_hrmp_open_request_ttl() -> Weight { // Minimum execution time: 2_000_000_000 nanoseconds. - Weight::from_ref_time(2_000_000_000_000 as u64) + Weight::from_ref_time(2_000_000_000_000) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_balance() -> Weight { - // Minimum execution time: 11_715 nanoseconds. - Weight::from_ref_time(11_895_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_434 nanoseconds. + Weight::from_ref_time(12_838_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/runtime_parachains_disputes.rs b/runtime/kusama/src/weights/runtime_parachains_disputes.rs index e5dac5d6b05f..98f985407e8b 100644 --- a/runtime/kusama/src/weights/runtime_parachains_disputes.rs +++ b/runtime/kusama/src/weights/runtime_parachains_disputes.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::disputes` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -46,8 +46,8 @@ pub struct WeightInfo(PhantomData); impl runtime_parachains::disputes::WeightInfo for WeightInfo { // Storage: ParasDisputes Frozen (r:0 w:1) fn force_unfreeze() -> Weight { - // Minimum execution time: 3_802 nanoseconds. - Weight::from_ref_time(3_998_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_165 nanoseconds. + Weight::from_ref_time(4_356_000) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/runtime_parachains_hrmp.rs b/runtime/kusama/src/weights/runtime_parachains_hrmp.rs index 45d9835bef9d..b3258788b827 100644 --- a/runtime/kusama/src/weights/runtime_parachains_hrmp.rs +++ b/runtime/kusama/src/weights/runtime_parachains_hrmp.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::hrmp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -53,10 +53,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_init_open_channel() -> Weight { - // Minimum execution time: 40_635 nanoseconds. - Weight::from_ref_time(41_119_000 as u64) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 42_143 nanoseconds. + Weight::from_ref_time(42_725_000) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:0) @@ -65,10 +65,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_accept_open_channel() -> Weight { - // Minimum execution time: 39_603 nanoseconds. - Weight::from_ref_time(39_921_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 42_718 nanoseconds. + Weight::from_ref_time(43_252_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Hrmp HrmpChannels (r:1 w:0) // Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) @@ -76,10 +76,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_close_channel() -> Weight { - // Minimum execution time: 36_362 nanoseconds. - Weight::from_ref_time(37_028_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 37_998 nanoseconds. + Weight::from_ref_time(38_684_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127) // Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1) @@ -90,18 +90,18 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// 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 { - // Minimum execution time: 856_131 nanoseconds. - Weight::from_ref_time(862_826_000 as u64) - // Standard Error: 78_515 - .saturating_add(Weight::from_ref_time(2_683_043 as u64).saturating_mul(i as u64)) - // Standard Error: 78_515 - .saturating_add(Weight::from_ref_time(2_703_843 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(e as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(e as u64))) + // Minimum execution time: 909_321 nanoseconds. + Weight::from_ref_time(915_087_000) + // Standard Error: 83_426 + .saturating_add(Weight::from_ref_time(2_776_230).saturating_mul(i.into())) + // Standard Error: 83_426 + .saturating_add(Weight::from_ref_time(2_860_951).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()))) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(i.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(e.into()))) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0) // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) @@ -113,14 +113,14 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpChannels (r:0 w:2) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_open(c: u32, ) -> Weight { - // Minimum execution time: 8_813 nanoseconds. - Weight::from_ref_time(301_248 as u64) - // Standard Error: 21_023 - .saturating_add(Weight::from_ref_time(15_715_851 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((7 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((6 as u64).saturating_mul(c as u64))) + // Minimum execution time: 9_996 nanoseconds. + Weight::from_ref_time(10_102_000) + // Standard Error: 12_007 + .saturating_add(Weight::from_ref_time(16_486_194).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()))) } // Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0) // Storage: Hrmp HrmpChannels (r:2 w:2) @@ -130,39 +130,39 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpChannelContents (r:0 w:2) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_close(c: u32, ) -> Weight { - // Minimum execution time: 5_575 nanoseconds. - Weight::from_ref_time(5_698_000 as u64) - // Standard Error: 6_879 - .saturating_add(Weight::from_ref_time(9_448_190 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((5 as u64).saturating_mul(c as u64))) + // Minimum execution time: 6_544 nanoseconds. + Weight::from_ref_time(281_356) + // Standard Error: 14_533 + .saturating_add(Weight::from_ref_time(10_078_230).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()))) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) /// The range of component `c` is `[0, 128]`. fn hrmp_cancel_open_request(c: u32, ) -> Weight { - // Minimum execution time: 24_071 nanoseconds. - Weight::from_ref_time(30_055_240 as u64) - // Standard Error: 1_352 - .saturating_add(Weight::from_ref_time(92_467 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 26_209 nanoseconds. + Weight::from_ref_time(32_345_013) + // Standard Error: 1_395 + .saturating_add(Weight::from_ref_time(94_298).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) /// The range of component `c` is `[0, 128]`. fn clean_open_channel_requests(c: u32, ) -> Weight { - // Minimum execution time: 4_101 nanoseconds. - Weight::from_ref_time(1_309_391 as u64) - // Standard Error: 4_811 - .saturating_add(Weight::from_ref_time(2_588_597 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + // Minimum execution time: 4_814 nanoseconds. + Weight::from_ref_time(3_057_523) + // Standard Error: 5_053 + .saturating_add(Weight::from_ref_time(2_736_286).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()))) } // Storage: Paras ParaLifecycles (r:2 w:0) // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) @@ -175,9 +175,9 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) fn force_open_hrmp_channel() -> Weight { - // Minimum execution time: 51_466 nanoseconds. - Weight::from_ref_time(52_179_000 as u64) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 53_933 nanoseconds. + Weight::from_ref_time(55_942_000) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(8)) } } diff --git a/runtime/kusama/src/weights/runtime_parachains_initializer.rs b/runtime/kusama/src/weights/runtime_parachains_initializer.rs index 650bfb8729fb..a88e4e76b92e 100644 --- a/runtime/kusama/src/weights/runtime_parachains_initializer.rs +++ b/runtime/kusama/src/weights/runtime_parachains_initializer.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::initializer` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -47,11 +47,11 @@ impl runtime_parachains::initializer::WeightInfo for We // Storage: System Digest (r:1 w:1) /// The range of component `d` is `[0, 65536]`. fn force_approve(d: u32, ) -> Weight { - // Minimum execution time: 7_505 nanoseconds. - Weight::from_ref_time(10_074_391 as u64) - // Standard Error: 7 - .saturating_add(Weight::from_ref_time(1_331 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 7_959 nanoseconds. + Weight::from_ref_time(10_697_366) + // Standard Error: 6 + .saturating_add(Weight::from_ref_time(1_327).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/kusama/src/weights/runtime_parachains_paras.rs b/runtime/kusama/src/weights/runtime_parachains_paras.rs index 8e7e0fff2171..559555f6f8c5 100644 --- a/runtime/kusama/src/weights/runtime_parachains_paras.rs +++ b/runtime/kusama/src/weights/runtime_parachains_paras.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::paras` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -52,21 +52,21 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras CodeByHash (r:0 w:1) /// The range of component `c` is `[1, 3145728]`. fn force_set_current_code(c: u32, ) -> Weight { - // Minimum execution time: 35_301 nanoseconds. - Weight::from_ref_time(35_709_000 as u64) + // Minimum execution time: 35_426 nanoseconds. + Weight::from_ref_time(35_644_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_275 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + .saturating_add(Weight::from_ref_time(2_312).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) /// The range of component `s` is `[1, 1048576]`. fn force_set_current_head(s: u32, ) -> Weight { - // Minimum execution time: 12_484 nanoseconds. - Weight::from_ref_time(12_861_000 as u64) + // Minimum execution time: 13_105 nanoseconds. + Weight::from_ref_time(13_469_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(909 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(907).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras FutureCodeHash (r:1 w:1) // Storage: Paras CurrentCodeHash (r:1 w:0) @@ -80,60 +80,60 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras UpgradeRestrictionSignal (r:0 w:1) /// The range of component `c` is `[1, 3145728]`. fn force_schedule_code_upgrade(c: u32, ) -> Weight { - // Minimum execution time: 59_066 nanoseconds. - Weight::from_ref_time(59_476_000 as u64) + // Minimum execution time: 59_910 nanoseconds. + Weight::from_ref_time(60_418_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_297 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + .saturating_add(Weight::from_ref_time(2_339).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras FutureCodeUpgrades (r:1 w:0) // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) /// The range of component `s` is `[1, 1048576]`. fn force_note_new_head(s: u32, ) -> Weight { - // Minimum execution time: 18_117 nanoseconds. - Weight::from_ref_time(18_425_000 as u64) + // Minimum execution time: 19_218 nanoseconds. + Weight::from_ref_time(19_527_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(910 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(909).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) // Storage: Paras ActionsQueue (r:1 w:1) fn force_queue_action() -> Weight { - // Minimum execution time: 22_620 nanoseconds. - Weight::from_ref_time(23_273_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 23_698 nanoseconds. + Weight::from_ref_time(24_173_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras PvfActiveVoteMap (r:1 w:0) // Storage: Paras CodeByHash (r:1 w:1) /// The range of component `c` is `[1, 3145728]`. fn add_trusted_validation_code(c: u32, ) -> Weight { - // Minimum execution time: 7_879 nanoseconds. - Weight::from_ref_time(7_958_000 as u64) + // Minimum execution time: 8_621 nanoseconds. + Weight::from_ref_time(8_888_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_283 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(2_322).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras CodeByHashRefs (r:1 w:0) // Storage: Paras CodeByHash (r:0 w:1) fn poke_unused_validation_code() -> Weight { - // Minimum execution time: 6_269 nanoseconds. - Weight::from_ref_time(6_409_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 7_096 nanoseconds. + Weight::from_ref_time(7_275_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) // Storage: Paras PvfActiveVoteMap (r:1 w:1) fn include_pvf_check_statement() -> Weight { - // Minimum execution time: 93_105 nanoseconds. - Weight::from_ref_time(94_985_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 92_359 nanoseconds. + Weight::from_ref_time(95_978_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) @@ -143,10 +143,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: System Digest (r:1 w:1) // Storage: Paras FutureCodeUpgrades (r:0 w:100) fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { - // Minimum execution time: 609_441 nanoseconds. - Weight::from_ref_time(615_952_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(104 as u64)) + // Minimum execution time: 658_136 nanoseconds. + Weight::from_ref_time(664_717_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(104)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) @@ -157,10 +157,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras UpgradeGoAheadSignal (r:0 w:100) // Storage: Paras FutureCodeHash (r:0 w:100) fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { - // Minimum execution time: 582_378 nanoseconds. - Weight::from_ref_time(585_955_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(204 as u64)) + // Minimum execution time: 622_504 nanoseconds. + Weight::from_ref_time(635_371_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(204)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) @@ -168,10 +168,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras PvfActiveVoteList (r:1 w:1) // Storage: Paras ActionsQueue (r:1 w:1) fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { - // Minimum execution time: 478_258 nanoseconds. - Weight::from_ref_time(485_575_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 508_515 nanoseconds. + Weight::from_ref_time(512_280_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) @@ -183,9 +183,9 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras CurrentCodeHash (r:0 w:100) // Storage: Paras UpcomingParasGenesis (r:0 w:100) fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { - // Minimum execution time: 644_795 nanoseconds. - Weight::from_ref_time(651_549_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(304 as u64)) + // Minimum execution time: 693_143 nanoseconds. + Weight::from_ref_time(706_638_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(304)) } } diff --git a/runtime/kusama/src/weights/runtime_parachains_paras_inherent.rs b/runtime/kusama/src/weights/runtime_parachains_paras_inherent.rs index c4cb58f3b0eb..51ce0bb2da3b 100644 --- a/runtime/kusama/src/weights/runtime_parachains_paras_inherent.rs +++ b/runtime/kusama/src/weights/runtime_parachains_paras_inherent.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::paras_inherent` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -77,12 +77,12 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) /// The range of component `v` is `[10, 200]`. fn enter_variable_disputes(v: u32, ) -> Weight { - // Minimum execution time: 808_425 nanoseconds. - Weight::from_ref_time(344_310_798 as u64) - // Standard Error: 21_870 - .saturating_add(Weight::from_ref_time(48_449_591 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(29 as u64)) - .saturating_add(T::DbWeight::get().writes(18 as u64)) + // Minimum execution time: 817_374 nanoseconds. + Weight::from_ref_time(355_653_989) + // Standard Error: 26_635 + .saturating_add(Weight::from_ref_time(48_169_665).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(29)) + .saturating_add(T::DbWeight::get().writes(18)) } // Storage: ParaInherent Included (r:1 w:1) // Storage: System ParentHash (r:1 w:0) @@ -115,10 +115,10 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) fn enter_bitfields() -> Weight { - // Minimum execution time: 325_574 nanoseconds. - Weight::from_ref_time(332_360_000 as u64) - .saturating_add(T::DbWeight::get().reads(26 as u64)) - .saturating_add(T::DbWeight::get().writes(17 as u64)) + // Minimum execution time: 333_179 nanoseconds. + Weight::from_ref_time(342_407_000) + .saturating_add(T::DbWeight::get().reads(26)) + .saturating_add(T::DbWeight::get().writes(17)) } // Storage: ParaInherent Included (r:1 w:1) // Storage: System ParentHash (r:1 w:0) @@ -153,12 +153,12 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) /// The range of component `v` is `[101, 200]`. fn enter_backed_candidates_variable(v: u32, ) -> Weight { - // Minimum execution time: 5_648_731 nanoseconds. - Weight::from_ref_time(876_233_814 as u64) - // Standard Error: 46_671 - .saturating_add(Weight::from_ref_time(48_048_616 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(29 as u64)) - .saturating_add(T::DbWeight::get().writes(16 as u64)) + // Minimum execution time: 5_626_906 nanoseconds. + Weight::from_ref_time(912_552_914) + // Standard Error: 47_749 + .saturating_add(Weight::from_ref_time(47_636_493).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) // Storage: System ParentHash (r:1 w:0) @@ -194,9 +194,9 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) fn enter_backed_candidate_code_upgrade() -> Weight { - // Minimum execution time: 38_109_414 nanoseconds. - Weight::from_ref_time(38_345_799_000 as u64) - .saturating_add(T::DbWeight::get().reads(31 as u64)) - .saturating_add(T::DbWeight::get().writes(16 as u64)) + // Minimum execution time: 38_549_462 nanoseconds. + Weight::from_ref_time(38_702_468_000) + .saturating_add(T::DbWeight::get().reads(31)) + .saturating_add(T::DbWeight::get().writes(16)) } } diff --git a/runtime/kusama/src/weights/runtime_parachains_ump.rs b/runtime/kusama/src/weights/runtime_parachains_ump.rs index 2fbad5020b19..b2849d37ebb9 100644 --- a/runtime/kusama/src/weights/runtime_parachains_ump.rs +++ b/runtime/kusama/src/weights/runtime_parachains_ump.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::ump` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("kusama-dev"), DB CACHE: 1024 @@ -46,26 +46,26 @@ pub struct WeightInfo(PhantomData); impl runtime_parachains::ump::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 51200]`. fn process_upward_message(s: u32, ) -> Weight { - // Minimum execution time: 9_700 nanoseconds. - Weight::from_ref_time(4_619_927 as u64) - // Standard Error: 12 - .saturating_add(Weight::from_ref_time(1_885 as u64).saturating_mul(s as u64)) + // Minimum execution time: 10_991 nanoseconds. + Weight::from_ref_time(5_407_947) + // Standard Error: 13 + .saturating_add(Weight::from_ref_time(1_937).saturating_mul(s.into())) } // Storage: Ump NeedsDispatch (r:1 w:1) // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) // Storage: Ump RelayDispatchQueues (r:0 w:1) // Storage: Ump RelayDispatchQueueSize (r:0 w:1) fn clean_ump_after_outgoing() -> Weight { - // Minimum execution time: 9_144 nanoseconds. - Weight::from_ref_time(9_352_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 10_134 nanoseconds. + Weight::from_ref_time(10_487_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Ump Overweight (r:1 w:1) fn service_overweight() -> Weight { - // Minimum execution time: 24_777 nanoseconds. - Weight::from_ref_time(25_125_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 27_101 nanoseconds. + Weight::from_ref_time(27_760_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/metrics/Cargo.toml b/runtime/metrics/Cargo.toml index 37069d8ed912..e00a9401da8a 100644 --- a/runtime/metrics/Cargo.toml +++ b/runtime/metrics/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "polkadot-runtime-metrics" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] -sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } parity-scale-codec = { version = "3.1.5", default-features = false } primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false } diff --git a/runtime/parachains/Cargo.toml b/runtime/parachains/Cargo.toml index 929cafeeccbf..18f0dae73668 100644 --- a/runtime/parachains/Cargo.toml +++ b/runtime/parachains/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "polkadot-runtime-parachains" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } @@ -14,29 +14,29 @@ serde = { version = "1.0.137", features = [ "derive" ], optional = true } derive_more = "0.99.17" bitflags = "1.3.2" -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-keystore = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.31" } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-keystore = { git = "https://github.com/paritytech/substrate", optional = true , branch = "polkadot-v0.9.36" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } -pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } xcm = { package = "xcm", path = "../../xcm", default-features = false } xcm-executor = { package = "xcm-executor", path = "../../xcm/xcm-executor", default-features = false } @@ -50,13 +50,14 @@ polkadot-runtime-metrics = { path = "../metrics", default-features = false} [dev-dependencies] futures = "0.3.21" hex-literal = "0.3.4" -keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-support-test = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-support-test = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../primitives/test-helpers"} -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } thousands = "0.2.0" assert_matches = "1" +serde_json = "1.0.85" [features] default = ["std"] diff --git a/runtime/parachains/src/builder.rs b/runtime/parachains/src/builder.rs index 42f54ecb3417..9a1c16e6aa1d 100644 --- a/runtime/parachains/src/builder.rs +++ b/runtime/parachains/src/builder.rs @@ -16,6 +16,7 @@ use crate::{ configuration, inclusion, initializer, paras, + paras::ParaKind, paras_inherent::{self}, scheduler, session_info, shared, }; @@ -25,9 +26,10 @@ use primitives::v2::{ collator_signature_payload, AvailabilityBitfield, BackedCandidate, CandidateCommitments, CandidateDescriptor, CandidateHash, CollatorId, CollatorSignature, CommittedCandidateReceipt, CompactStatement, CoreIndex, CoreOccupied, DisputeStatement, DisputeStatementSet, GroupIndex, - HeadData, Id as ParaId, InherentData as ParachainsInherentData, InvalidDisputeStatementKind, - PersistedValidationData, SessionIndex, SigningContext, UncheckedSigned, - ValidDisputeStatementKind, ValidationCode, ValidatorId, ValidatorIndex, ValidityAttestation, + 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::{ @@ -65,7 +67,7 @@ fn byte32_slice_from(n: u32) -> [u8; 32] { /// Paras inherent `enter` benchmark scenario builder. pub(crate) struct BenchBuilder { /// Active validators. Validators should be declared prior to all other setup. - validators: Option>, + validators: Option>, /// Starting block number; we expect it to get incremented on session setup. block_number: T::BlockNumber, /// Starting session; we expect it to get incremented on session setup. @@ -344,7 +346,7 @@ impl BenchBuilder { paras::ParaGenesisArgs { genesis_head: Self::mock_head_data(), validation_code: mock_validation_code(), - parachain: true, + para_kind: ParaKind::Parachain, }, ) .unwrap(); @@ -410,7 +412,7 @@ impl BenchBuilder { assert_eq!(>::session_index(), target_session); // We need to refetch validators since they have been shuffled. - let validators_shuffled: Vec<_> = session_info::Pallet::::session_info(target_session) + let validators_shuffled = session_info::Pallet::::session_info(target_session) .unwrap() .validators .clone(); @@ -549,7 +551,7 @@ impl BenchBuilder { .iter() .take(*num_votes as usize) .map(|val_idx| { - let public = validators.get(val_idx.0 as usize).unwrap(); + let public = validators.get(*val_idx).unwrap(); let sig = UncheckedSigned::::benchmark_sign( public, CompactStatement::Valid(candidate_hash.clone()), @@ -606,7 +608,7 @@ impl BenchBuilder { self.dispute_statements.get(&seed).cloned().unwrap_or(validators.len() as u32); let statements = (0..statements_len) .map(|validator_index| { - let validator_public = &validators.get(validator_index as usize).expect("Test case is not borked. `ValidatorIndex` out of bounds of `ValidatorId`s."); + let validator_public = &validators.get(ValidatorIndex::from(validator_index)).expect("Test case is not borked. `ValidatorIndex` out of bounds of `ValidatorId`s."); // We need dispute statements on each side. And we don't want a revert log // so we make sure that we have a super majority with valid statements. diff --git a/runtime/parachains/src/configuration.rs b/runtime/parachains/src/configuration.rs index 2ebaff1b8282..113fad1d7a57 100644 --- a/runtime/parachains/src/configuration.rs +++ b/runtime/parachains/src/configuration.rs @@ -19,7 +19,7 @@ //! Configuration can change only at session boundaries and is buffered until then. use crate::shared; -use frame_support::{pallet_prelude::*, weights::constants::WEIGHT_PER_MILLIS}; +use frame_support::{pallet_prelude::*, weights::constants::WEIGHT_REF_TIME_PER_MILLIS}; use frame_system::pallet_prelude::*; use parity_scale_codec::{Decode, Encode}; use primitives::v2::{Balance, SessionIndex, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE}; @@ -285,8 +285,10 @@ impl> Default for HostConfiguration Pallet { let mut importer = DisputeStateImporter::new(dispute_state, now); for (i, (statement, validator_index, signature)) in set.statements.iter().enumerate() { // assure the validator index and is present in the session info - let validator_public = match session_info.validators.get(validator_index.0 as usize) - { + let validator_public = match session_info.validators.get(*validator_index) { None => { filter.remove_index(i); continue @@ -1113,7 +1112,7 @@ impl Pallet { // it's sufficient to count the votes in the statement set after they set.statements.iter().for_each(|(statement, v_i, _signature)| { if Some(true) == - summary.new_participants.get(v_i.0 as usize).map(|b| b.as_ref().clone()) + summary.new_participants.get(v_i.0 as usize).map(|b| *b.as_ref()) { match statement { // `summary.new_flags` contains the spam free votes. diff --git a/runtime/parachains/src/disputes/slashing.rs b/runtime/parachains/src/disputes/slashing.rs index fd6708de6ba0..2dfdc87c4b4e 100644 --- a/runtime/parachains/src/disputes/slashing.rs +++ b/runtime/parachains/src/disputes/slashing.rs @@ -257,7 +257,7 @@ where let keys = losers .into_iter() - .filter_map(|i| session_info.validators.get(i.0 as usize).cloned().map(|id| (i, id))) + .filter_map(|i| session_info.validators.get(i).cloned().map(|id| (i, id))) .collect(); let unapplied = PendingSlashes { keys, kind }; >::insert(session_index, candidate_hash, unapplied); diff --git a/runtime/parachains/src/disputes/slashing/benchmarking.rs b/runtime/parachains/src/disputes/slashing/benchmarking.rs index 2a21c3a0f62b..552172dc1901 100644 --- a/runtime/parachains/src/disputes/slashing/benchmarking.rs +++ b/runtime/parachains/src/disputes/slashing/benchmarking.rs @@ -80,7 +80,7 @@ where let session_index = crate::shared::Pallet::::session_index(); let session_info = crate::session_info::Pallet::::session_info(session_index); let session_info = session_info.unwrap(); - let validator_id = session_info.validators[0].clone(); + let validator_id = session_info.validators.get(ValidatorIndex::from(0)).unwrap().clone(); let key = (PARACHAIN_KEY_TYPE_ID, validator_id.clone()); let key_owner_proof = pallet_session::historical::Pallet::::prove(key).unwrap(); diff --git a/runtime/parachains/src/hrmp.rs b/runtime/parachains/src/hrmp.rs index 53ad6781048f..ed8e554bc498 100644 --- a/runtime/parachains/src/hrmp.rs +++ b/runtime/parachains/src/hrmp.rs @@ -751,10 +751,10 @@ impl Pallet { let ingress = ::HrmpIngressChannelsIndex::take(outgoing_para) .into_iter() - .map(|sender| HrmpChannelId { sender, recipient: outgoing_para.clone() }); + .map(|sender| HrmpChannelId { sender, recipient: *outgoing_para }); let egress = ::HrmpEgressChannelsIndex::take(outgoing_para) .into_iter() - .map(|recipient| HrmpChannelId { sender: outgoing_para.clone(), recipient }); + .map(|recipient| HrmpChannelId { sender: *outgoing_para, recipient }); let mut to_close = ingress.chain(egress).collect::>(); to_close.sort(); to_close.dedup(); @@ -1075,7 +1075,7 @@ impl Pallet { channel.total_size += inbound.data.len() as u32; // compute the new MQC head of the channel - let prev_head = channel.mqc_head.clone().unwrap_or(Default::default()); + let prev_head = channel.mqc_head.unwrap_or(Default::default()); let new_head = BlakeTwo256::hash_of(&( prev_head, inbound.sent_at, @@ -1149,11 +1149,11 @@ impl Pallet { let channel_id = HrmpChannelId { sender: origin, recipient }; ensure!( ::HrmpOpenChannelRequests::get(&channel_id).is_none(), - Error::::OpenHrmpChannelAlreadyExists, + Error::::OpenHrmpChannelAlreadyRequested, ); ensure!( ::HrmpChannels::get(&channel_id).is_none(), - Error::::OpenHrmpChannelAlreadyRequested, + Error::::OpenHrmpChannelAlreadyExists, ); let egress_cnt = diff --git a/runtime/parachains/src/hrmp/benchmarking.rs b/runtime/parachains/src/hrmp/benchmarking.rs index 7ea14b1dc922..562e735e6a50 100644 --- a/runtime/parachains/src/hrmp/benchmarking.rs +++ b/runtime/parachains/src/hrmp/benchmarking.rs @@ -17,7 +17,7 @@ use crate::{ configuration::Pallet as Configuration, hrmp::{Pallet as Hrmp, *}, - paras::{Pallet as Paras, ParachainsCache}, + paras::{Pallet as Paras, ParaKind, ParachainsCache}, shared::Pallet as Shared, }; use frame_support::{assert_ok, traits::Currency}; @@ -31,7 +31,7 @@ fn register_parachain_with_balance(id: ParaId, balance: BalanceOf) &mut parachains, id, &crate::paras::ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: vec![1].into(), validation_code: vec![1].into(), }, diff --git a/runtime/parachains/src/hrmp/tests.rs b/runtime/parachains/src/hrmp/tests.rs index 9e0d0646d057..85cdc459ffb9 100644 --- a/runtime/parachains/src/hrmp/tests.rs +++ b/runtime/parachains/src/hrmp/tests.rs @@ -15,9 +15,12 @@ // along with Polkadot. If not, see . use super::*; -use crate::mock::{ - new_test_ext, Configuration, Hrmp, MockGenesisConfig, Paras, ParasShared, - RuntimeEvent as MockEvent, RuntimeOrigin, System, Test, +use crate::{ + mock::{ + new_test_ext, Configuration, Hrmp, MockGenesisConfig, Paras, ParasShared, + RuntimeEvent as MockEvent, RuntimeOrigin, System, Test, + }, + paras::ParaKind, }; use frame_support::{assert_noop, assert_ok, traits::Currency as _}; use primitives::v2::BlockNumber; @@ -130,7 +133,7 @@ fn register_parachain_with_balance(id: ParaId, balance: Balance) { assert_ok!(Paras::schedule_para_initialize( id, crate::paras::ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: vec![1].into(), validation_code: vec![1].into(), }, diff --git a/runtime/parachains/src/inclusion/mod.rs b/runtime/parachains/src/inclusion/mod.rs index f74a8cfd3f8d..1df6c141e9df 100644 --- a/runtime/parachains/src/inclusion/mod.rs +++ b/runtime/parachains/src/inclusion/mod.rs @@ -102,7 +102,7 @@ impl CandidatePendingAvailability { /// Get the core index. pub(crate) fn core_occupied(&self) -> CoreIndex { - self.core.clone() + self.core } /// Get the candidate hash. @@ -383,7 +383,7 @@ impl Pallet { let mut freed_cores = Vec::with_capacity(expected_bits); for (para_id, pending_availability) in assigned_paras_record .into_iter() - .filter_map(|x| x) + .flatten() .filter_map(|(id, p)| p.map(|p| (id, p))) { if pending_availability.availability_votes.count_ones() >= threshold { @@ -644,8 +644,7 @@ impl Pallet { }; // one more sweep for actually writing to storage. - let core_indices = - core_indices_and_backers.iter().map(|&(ref c, _, _)| c.clone()).collect(); + let core_indices = core_indices_and_backers.iter().map(|&(ref c, _, _)| *c).collect(); for (candidate, (core, backers, group)) in candidates.into_iter().zip(core_indices_and_backers) { diff --git a/runtime/parachains/src/inclusion/tests.rs b/runtime/parachains/src/inclusion/tests.rs index de3199c366a7..00369fb67e75 100644 --- a/runtime/parachains/src/inclusion/tests.rs +++ b/runtime/parachains/src/inclusion/tests.rs @@ -22,7 +22,7 @@ use crate::{ new_test_ext, Configuration, MockGenesisConfig, ParaInclusion, Paras, ParasShared, System, Test, }, - paras::ParaGenesisArgs, + paras::{ParaGenesisArgs, ParaKind}, paras_inherent::DisputedBitfield, scheduler::AssignmentKind, }; @@ -51,18 +51,18 @@ fn default_config() -> HostConfiguration { config } -pub(crate) fn genesis_config(paras: Vec<(ParaId, bool)>) -> MockGenesisConfig { +pub(crate) fn genesis_config(paras: Vec<(ParaId, ParaKind)>) -> MockGenesisConfig { MockGenesisConfig { paras: paras::GenesisConfig { paras: paras .into_iter() - .map(|(id, is_chain)| { + .map(|(id, para_kind)| { ( id, ParaGenesisArgs { genesis_head: Vec::new().into(), validation_code: dummy_validation_code(), - parachain: is_chain, + para_kind, }, ) }) @@ -310,7 +310,11 @@ fn collect_pending_cleans_up_pending() { let chain_b = ParaId::from(2_u32); let thread_a = ParaId::from(3_u32); - let paras = vec![(chain_a, true), (chain_b, true), (thread_a, false)]; + let paras = vec![ + (chain_a, ParaKind::Parachain), + (chain_b, ParaKind::Parachain), + (thread_a, ParaKind::Parathread), + ]; new_test_ext(genesis_config(paras)).execute_with(|| { let default_candidate = TestCandidateBuilder::default().build(); >::insert( @@ -368,7 +372,11 @@ fn bitfield_checks() { let chain_b = ParaId::from(2_u32); let thread_a = ParaId::from(3_u32); - let paras = vec![(chain_a, true), (chain_b, true), (thread_a, false)]; + let paras = vec![ + (chain_a, ParaKind::Parachain), + (chain_b, ParaKind::Parachain), + (thread_a, ParaKind::Parathread), + ]; let validators = vec![ Sr25519Keyring::Alice, Sr25519Keyring::Bob, @@ -711,7 +719,11 @@ fn supermajority_bitfields_trigger_availability() { let chain_b = ParaId::from(2_u32); let thread_a = ParaId::from(3_u32); - let paras = vec![(chain_a, true), (chain_b, true), (thread_a, false)]; + let paras = vec![ + (chain_a, ParaKind::Parachain), + (chain_b, ParaKind::Parachain), + (thread_a, ParaKind::Parathread), + ]; let validators = vec![ Sr25519Keyring::Alice, Sr25519Keyring::Bob, @@ -899,7 +911,11 @@ fn candidate_checks() { // The block number of the relay-parent for testing. const RELAY_PARENT_NUM: BlockNumber = 4; - let paras = vec![(chain_a, true), (chain_b, true), (thread_a, false)]; + let paras = vec![ + (chain_a, ParaKind::Parachain), + (chain_b, ParaKind::Parachain), + (thread_a, ParaKind::Parathread), + ]; let validators = vec![ Sr25519Keyring::Alice, Sr25519Keyring::Bob, @@ -1442,7 +1458,11 @@ fn backing_works() { // The block number of the relay-parent for testing. const RELAY_PARENT_NUM: BlockNumber = 4; - let paras = vec![(chain_a, true), (chain_b, true), (thread_a, false)]; + let paras = vec![ + (chain_a, ParaKind::Parachain), + (chain_b, ParaKind::Parachain), + (thread_a, ParaKind::Parathread), + ]; let validators = vec![ Sr25519Keyring::Alice, Sr25519Keyring::Bob, @@ -1722,7 +1742,7 @@ fn can_include_candidate_with_ok_code_upgrade() { // The block number of the relay-parent for testing. const RELAY_PARENT_NUM: BlockNumber = 4; - let paras = vec![(chain_a, true)]; + let paras = vec![(chain_a, ParaKind::Parachain)]; let validators = vec![ Sr25519Keyring::Alice, Sr25519Keyring::Bob, @@ -1827,7 +1847,11 @@ fn session_change_wipes() { let chain_b = ParaId::from(2_u32); let thread_a = ParaId::from(3_u32); - let paras = vec![(chain_a, true), (chain_b, true), (thread_a, false)]; + let paras = vec![ + (chain_a, ParaKind::Parachain), + (chain_b, ParaKind::Parachain), + (thread_a, ParaKind::Parathread), + ]; let validators = vec![ Sr25519Keyring::Alice, Sr25519Keyring::Bob, diff --git a/runtime/parachains/src/initializer.rs b/runtime/parachains/src/initializer.rs index eaa4510fafcf..ef00e5b884cc 100644 --- a/runtime/parachains/src/initializer.rs +++ b/runtime/parachains/src/initializer.rs @@ -247,7 +247,7 @@ impl Pallet { let validators = shared::Pallet::::initializer_on_new_session( session_index, - random_seed.clone(), + random_seed, &new_config, all_validators, ); diff --git a/runtime/parachains/src/initializer/tests.rs b/runtime/parachains/src/initializer/tests.rs index 7fdf8b6b4a57..d1d884200527 100644 --- a/runtime/parachains/src/initializer/tests.rs +++ b/runtime/parachains/src/initializer/tests.rs @@ -21,6 +21,7 @@ use crate::mock::{ use primitives::v2::{HeadData, Id as ParaId}; use test_helpers::dummy_validation_code; +use crate::paras::ParaKind; use frame_support::{ assert_ok, traits::{OnFinalize, OnInitialize}, @@ -90,7 +91,7 @@ fn scheduled_cleanup_performed() { let c = ParaId::from(123); let mock_genesis = crate::paras::ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: HeadData(vec![4, 5, 6]), validation_code: dummy_validation_code(), }; diff --git a/runtime/parachains/src/paras/benchmarking/pvf_check.rs b/runtime/parachains/src/paras/benchmarking/pvf_check.rs index a89315c2857b..e1400ac4297d 100644 --- a/runtime/parachains/src/paras/benchmarking/pvf_check.rs +++ b/runtime/parachains/src/paras/benchmarking/pvf_check.rs @@ -140,7 +140,7 @@ where &mut parachains, id, &ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: HeadData(vec![1, 2, 3, 4]), validation_code: old_validation_code, }, @@ -159,7 +159,7 @@ where let r = Pallet::::schedule_para_initialize( id, ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: HeadData(vec![1, 2, 3, 4]), validation_code: validation_code(), }, diff --git a/runtime/parachains/src/paras/mod.rs b/runtime/parachains/src/paras/mod.rs index 273db30e2839..c4fadcf5642b 100644 --- a/runtime/parachains/src/paras/mod.rs +++ b/runtime/parachains/src/paras/mod.rs @@ -115,7 +115,7 @@ use primitives::v2::{ ConsensusLog, HeadData, Id as ParaId, PvfCheckStatement, SessionIndex, UpgradeGoAhead, UpgradeRestriction, ValidationCode, ValidationCodeHash, ValidatorSignature, }; -use scale_info::TypeInfo; +use scale_info::{Type, TypeInfo}; use sp_core::RuntimeDebug; use sp_runtime::{ traits::{AppVerify, One, Saturating}, @@ -291,8 +291,76 @@ pub struct ParaGenesisArgs { pub genesis_head: HeadData, /// The initial validation code to use. pub validation_code: ValidationCode, - /// True if parachain, false if parathread. - pub parachain: bool, + /// Parachain or Parathread. + #[cfg_attr(feature = "std", serde(rename = "parachain"))] + pub para_kind: ParaKind, +} + +/// Distinguishes between Parachain and Parathread +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +pub enum ParaKind { + Parathread, + Parachain, +} + +#[cfg(feature = "std")] +impl Serialize for ParaKind { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + match self { + ParaKind::Parachain => serializer.serialize_bool(true), + ParaKind::Parathread => serializer.serialize_bool(false), + } + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for ParaKind { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + match serde::de::Deserialize::deserialize(deserializer) { + Ok(true) => Ok(ParaKind::Parachain), + Ok(false) => Ok(ParaKind::Parathread), + _ => Err(serde::de::Error::custom("invalid ParaKind serde representation")), + } + } +} + +// Manual encoding, decoding, and TypeInfo as the parakind field in ParaGenesisArgs used to be a bool +impl Encode for ParaKind { + fn size_hint(&self) -> usize { + true.size_hint() + } + + fn using_encoded R>(&self, f: F) -> R { + match self { + ParaKind::Parachain => true.using_encoded(f), + ParaKind::Parathread => false.using_encoded(f), + } + } +} + +impl Decode for ParaKind { + fn decode( + input: &mut I, + ) -> Result { + match bool::decode(input) { + Ok(true) => Ok(ParaKind::Parachain), + Ok(false) => Ok(ParaKind::Parathread), + _ => Err("Invalid ParaKind representation".into()), + } + } +} + +impl TypeInfo for ParaKind { + type Identity = bool; + fn type_info() -> Type { + bool::type_info() + } } /// This enum describes a reason why a particular PVF pre-checking vote was initiated. When the @@ -591,7 +659,7 @@ pub mod pallet { /// Past code of parachains. The parachains themselves may not be registered anymore, /// but we also keep their code on-chain for the same amount of time as outdated code - /// to keep it available for secondary checkers. + /// to keep it available for approval checkers. #[pallet::storage] #[pallet::getter(fn past_code_meta)] pub(super) type PastCodeMeta = @@ -2021,11 +2089,12 @@ impl Pallet { id: ParaId, genesis_data: &ParaGenesisArgs, ) { - if genesis_data.parachain { - parachains.add(id); - ParaLifecycles::::insert(&id, ParaLifecycle::Parachain); - } else { - ParaLifecycles::::insert(&id, ParaLifecycle::Parathread); + match genesis_data.para_kind { + ParaKind::Parachain => { + parachains.add(id); + ParaLifecycles::::insert(&id, ParaLifecycle::Parachain); + }, + ParaKind::Parathread => ParaLifecycles::::insert(&id, ParaLifecycle::Parathread), } // HACK: see the notice in `schedule_para_initialize`. diff --git a/runtime/parachains/src/paras/tests.rs b/runtime/parachains/src/paras/tests.rs index 766fa00d01b3..f110e2a0d38a 100644 --- a/runtime/parachains/src/paras/tests.rs +++ b/runtime/parachains/src/paras/tests.rs @@ -222,7 +222,7 @@ fn schedule_para_init_rejects_empty_code() { Paras::schedule_para_initialize( 1000.into(), ParaGenesisArgs { - parachain: false, + para_kind: ParaKind::Parathread, genesis_head: dummy_head_data(), validation_code: ValidationCode(vec![]), } @@ -233,7 +233,7 @@ fn schedule_para_init_rejects_empty_code() { assert_ok!(Paras::schedule_para_initialize( 1000.into(), ParaGenesisArgs { - parachain: false, + para_kind: ParaKind::Parathread, genesis_head: dummy_head_data(), validation_code: ValidationCode(vec![1]), } @@ -248,7 +248,7 @@ fn para_past_code_pruning_in_initialize() { ( 0u32.into(), ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: dummy_head_data(), validation_code: dummy_validation_code(), }, @@ -256,7 +256,7 @@ fn para_past_code_pruning_in_initialize() { ( 1u32.into(), ParaGenesisArgs { - parachain: false, + para_kind: ParaKind::Parathread, genesis_head: dummy_head_data(), validation_code: dummy_validation_code(), }, @@ -316,7 +316,7 @@ fn note_new_head_sets_head() { let paras = vec![( 0u32.into(), ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: dummy_head_data(), validation_code: dummy_validation_code(), }, @@ -349,7 +349,7 @@ fn note_past_code_sets_up_pruning_correctly() { ( 0u32.into(), ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: dummy_head_data(), validation_code: dummy_validation_code(), }, @@ -357,7 +357,7 @@ fn note_past_code_sets_up_pruning_correctly() { ( 1u32.into(), ParaGenesisArgs { - parachain: false, + para_kind: ParaKind::Parathread, genesis_head: dummy_head_data(), validation_code: dummy_validation_code(), }, @@ -402,7 +402,7 @@ fn code_upgrade_applied_after_delay() { let paras = vec![( 0u32.into(), ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: dummy_head_data(), validation_code: original_code.clone(), }, @@ -505,7 +505,7 @@ fn code_upgrade_applied_after_delay_even_when_late() { let paras = vec![( 0u32.into(), ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: dummy_head_data(), validation_code: original_code.clone(), }, @@ -590,7 +590,7 @@ fn submit_code_change_when_not_allowed_is_err() { let paras = vec![( 0u32.into(), ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: dummy_head_data(), validation_code: vec![1, 2, 3].into(), }, @@ -658,7 +658,7 @@ fn upgrade_restriction_elapsed_doesnt_mean_can_upgrade() { let paras = vec![( 0u32.into(), ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: dummy_head_data(), validation_code: vec![1, 2, 3].into(), }, @@ -721,7 +721,7 @@ fn full_parachain_cleanup_storage() { let paras = vec![( 0u32.into(), ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: dummy_head_data(), validation_code: original_code.clone(), }, @@ -827,7 +827,7 @@ fn cannot_offboard_ongoing_pvf_check() { let paras = vec![( para_id, ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: Default::default(), validation_code: existing_code, }, @@ -900,7 +900,7 @@ fn para_incoming_at_session() { assert_ok!(Paras::schedule_para_initialize( b, ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: vec![1].into(), validation_code: code_b.clone(), }, @@ -909,7 +909,7 @@ fn para_incoming_at_session() { assert_ok!(Paras::schedule_para_initialize( a, ParaGenesisArgs { - parachain: false, + para_kind: ParaKind::Parathread, genesis_head: vec![2].into(), validation_code: code_a.clone(), }, @@ -918,7 +918,7 @@ fn para_incoming_at_session() { assert_ok!(Paras::schedule_para_initialize( c, ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: vec![3].into(), validation_code: code_c.clone(), }, @@ -994,7 +994,7 @@ fn code_hash_at_returns_up_to_end_of_code_retention_period() { let paras = vec![( 0u32.into(), ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: dummy_head_data(), validation_code: vec![1, 2, 3].into(), }, @@ -1084,7 +1084,7 @@ fn pvf_check_coalescing_onboarding_and_upgrade() { let paras = vec![( a, ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: Default::default(), validation_code: existing_code, }, @@ -1117,7 +1117,7 @@ fn pvf_check_coalescing_onboarding_and_upgrade() { assert_ok!(Paras::schedule_para_initialize( b, ParaGenesisArgs { - parachain: true, + para_kind: ParaKind::Parachain, genesis_head: vec![2].into(), validation_code: validation_code.clone(), }, @@ -1185,7 +1185,7 @@ fn pvf_check_onboarding_reject_on_expiry() { assert_ok!(Paras::schedule_para_initialize( a, ParaGenesisArgs { - parachain: false, + para_kind: ParaKind::Parathread, genesis_head: vec![2].into(), validation_code: validation_code.clone(), }, @@ -1224,7 +1224,7 @@ fn pvf_check_upgrade_reject() { let paras = vec![( a, ParaGenesisArgs { - parachain: false, + para_kind: ParaKind::Parathread, genesis_head: Default::default(), validation_code: old_code, }, @@ -1359,7 +1359,7 @@ fn pvf_check_submit_vote() { assert_ok!(Paras::schedule_para_initialize( 1000.into(), ParaGenesisArgs { - parachain: false, + para_kind: ParaKind::Parathread, genesis_head: vec![2].into(), validation_code: code_a.clone(), }, @@ -1446,7 +1446,7 @@ fn include_pvf_check_statement_refunds_weight() { let paras = vec![( a, ParaGenesisArgs { - parachain: false, + para_kind: ParaKind::Parathread, genesis_head: Default::default(), validation_code: old_code, }, @@ -1723,3 +1723,41 @@ fn verify_upgrade_restriction_signal_is_externally_accessible() { ); }); } + +#[test] +fn parakind_encodes_decodes_to_bool_scale() { + let chain_kind = ParaKind::Parachain.encode(); + let chain_bool = true.encode(); + assert_eq!(chain_kind, chain_bool); + + let chain_dec = ParaKind::decode(&mut chain_kind.as_slice()); + assert_eq!(chain_dec, Ok(ParaKind::Parachain)); + + let thread_kind = ParaKind::Parathread.encode(); + let thread_bool = false.encode(); + assert_eq!(thread_kind, thread_bool); + + let thread_dec = ParaKind::decode(&mut thread_kind.as_slice()); + assert_eq!(thread_dec, Ok(ParaKind::Parathread)); + + assert_eq!(bool::type_info(), ParaKind::type_info()); +} + +#[test] +fn parakind_encodes_decodes_to_bool_serde() { + let chain = ParaKind::Parachain; + let ser_chain = serde_json::to_string(&ParaKind::Parachain).unwrap(); + let de_chain: ParaKind = serde_json::from_str(&ser_chain).unwrap(); + assert_eq!(chain, de_chain); + + let ser_true = serde_json::to_string(&true).unwrap(); + assert_eq!(ser_true, ser_chain); + + let thread = ParaKind::Parathread; + let ser_thread = serde_json::to_string(&thread).unwrap(); + let de_thread: ParaKind = serde_json::from_str(&ser_thread).unwrap(); + assert_eq!(thread, de_thread); + + let ser_false = serde_json::to_string(&false).unwrap(); + assert_eq!(ser_false, ser_thread); +} diff --git a/runtime/parachains/src/paras_inherent/mod.rs b/runtime/parachains/src/paras_inherent/mod.rs index 188a8f677979..a053e3dbfaf9 100644 --- a/runtime/parachains/src/paras_inherent/mod.rs +++ b/runtime/parachains/src/paras_inherent/mod.rs @@ -513,7 +513,7 @@ impl Pallet { METRICS.on_candidates_sanitized(backed_candidates.len() as u64); // Process backed candidates according to scheduled cores. - let parent_storage_root = parent_header.state_root().clone(); + let parent_storage_root = *parent_header.state_root(); let inclusion::ProcessedCandidates::<::Hash> { core_indices: occupied, candidate_receipt_with_backing_validator_indices, @@ -711,7 +711,7 @@ impl Pallet { let scheduled = >::scheduled(); let relay_parent_number = now - One::one(); - let parent_storage_root = parent_header.state_root().clone(); + let parent_storage_root = *parent_header.state_root(); let check_ctx = CandidateCheckContext::::new(now, relay_parent_number); let backed_candidates = sanitize_backed_candidates::( @@ -1201,7 +1201,7 @@ fn compute_entropy(parent_hash: T::Hash) -> [u8; 32] { // known 2 epochs ago. it is marginally better than using the parent block // hash since it's harder to influence the VRF output than the block hash. let vrf_random = ParentBlockRandomness::::random(&CANDIDATE_SEED_SUBJECT[..]).0; - let mut entropy: [u8; 32] = CANDIDATE_SEED_SUBJECT.clone(); + let mut entropy: [u8; 32] = CANDIDATE_SEED_SUBJECT; if let Some(vrf_random) = vrf_random { entropy.as_mut().copy_from_slice(vrf_random.as_ref()); } else { diff --git a/runtime/parachains/src/runtime_api_impl/v2.rs b/runtime/parachains/src/runtime_api_impl/v2.rs index 77ea96742b54..57345a819de0 100644 --- a/runtime/parachains/src/runtime_api_impl/v2.rs +++ b/runtime/parachains/src/runtime_api_impl/v2.rs @@ -107,7 +107,7 @@ pub fn availability_cores() -> Vec>::pending_availability(para_id) .expect("Occupied core always has pending availability; qed"); - let backed_in_number = pending_availability.backed_in_number().clone(); + let backed_in_number = *pending_availability.backed_in_number(); OccupiedCore { next_up_on_available: >::next_up_on_available( CoreIndex(i as u32), @@ -135,7 +135,7 @@ pub fn availability_cores() -> Vec>::pending_availability(para_id) .expect("Occupied core always has pending availability; qed"); - let backed_in_number = pending_availability.backed_in_number().clone(); + let backed_in_number = *pending_availability.backed_in_number(); OccupiedCore { next_up_on_available: >::next_up_on_available( CoreIndex(i as u32), diff --git a/runtime/parachains/src/scheduler.rs b/runtime/parachains/src/scheduler.rs index 0185817b2aa1..6eb1b732705f 100644 --- a/runtime/parachains/src/scheduler.rs +++ b/runtime/parachains/src/scheduler.rs @@ -483,7 +483,7 @@ impl Pallet { Some(CoreAssignment { kind: AssignmentKind::Parachain, para_id: parachains[core_index], - core: core.clone(), + core, group_idx: Self::group_assigned_to_core(core, now).expect( "core is not out of bounds and we are guaranteed \ to be after the most recent session start; qed", @@ -496,7 +496,7 @@ impl Pallet { parathread_queue.take_next_on_core(core_offset).map(|entry| CoreAssignment { kind: AssignmentKind::Parathread(entry.claim.1, entry.retries), para_id: entry.claim.0, - core: core.clone(), + core, group_idx: Self::group_assigned_to_core(core, now).expect( "core is not out of bounds and we are guaranteed \ to be after the most recent session start; qed", @@ -610,11 +610,9 @@ impl Pallet { (at - session_start_block) / config.group_rotation_frequency.into(); let rotations_since_session_start = - match >::try_into(rotations_since_session_start) { - Ok(i) => i, - Err(_) => 0, // can only happen if rotations occur only once every u32::max(), - // so functionally no difference in behavior. - }; + >::try_into(rotations_since_session_start).unwrap_or(0); + // Error case can only happen if rotations occur only once every u32::max(), + // so functionally no difference in behavior. let group_idx = (core.0 as usize + rotations_since_session_start as usize) % validator_groups.len(); diff --git a/runtime/parachains/src/scheduler/tests.rs b/runtime/parachains/src/scheduler/tests.rs index b2b5e4236dd5..40ff9db82871 100644 --- a/runtime/parachains/src/scheduler/tests.rs +++ b/runtime/parachains/src/scheduler/tests.rs @@ -26,16 +26,16 @@ use crate::{ mock::{ new_test_ext, Configuration, MockGenesisConfig, Paras, ParasShared, Scheduler, System, Test, }, - paras::ParaGenesisArgs, + paras::{ParaGenesisArgs, ParaKind}, }; -fn schedule_blank_para(id: ParaId, is_chain: bool) { +fn schedule_blank_para(id: ParaId, parakind: ParaKind) { assert_ok!(Paras::schedule_para_initialize( id, ParaGenesisArgs { genesis_head: Vec::new().into(), validation_code: vec![1, 2, 3].into(), - parachain: is_chain, + para_kind: parakind, } )); } @@ -122,7 +122,7 @@ fn add_parathread_claim_works() { let collator = CollatorId::from(Sr25519Keyring::Alice.public()); new_test_ext(genesis_config).execute_with(|| { - schedule_blank_para(thread_id, false); + schedule_blank_para(thread_id, ParaKind::Parathread); assert!(!Paras::is_parathread(thread_id)); @@ -203,7 +203,7 @@ fn cannot_add_claim_when_no_parathread_cores() { let collator = CollatorId::from(Sr25519Keyring::Alice.public()); new_test_ext(genesis_config).execute_with(|| { - schedule_blank_para(thread_id, false); + schedule_blank_para(thread_id, ParaKind::Parathread); assert!(!Paras::is_parathread(thread_id)); @@ -239,9 +239,9 @@ fn session_change_prunes_cores_beyond_retries_and_those_from_non_live_parathread // threads a, b, and c will be live in next session, but not d. { - schedule_blank_para(thread_a, false); - schedule_blank_para(thread_b, false); - schedule_blank_para(thread_c, false); + schedule_blank_para(thread_a, ParaKind::Parathread); + schedule_blank_para(thread_b, ParaKind::Parathread); + schedule_blank_para(thread_c, ParaKind::Parathread); } // set up a queue as if `n_cores` was 4 and with some with many retries. @@ -334,8 +334,8 @@ fn session_change_shuffles_validators() { let chain_b = ParaId::from(2_u32); // ensure that we have 5 groups by registering 2 parachains. - schedule_blank_para(chain_a, true); - schedule_blank_para(chain_b, true); + schedule_blank_para(chain_a, ParaKind::Parachain); + schedule_blank_para(chain_b, ParaKind::Parachain); run_to_block(1, |number| match number { 1 => Some(SessionChangeNotification { @@ -392,9 +392,9 @@ fn session_change_takes_only_max_per_core() { let chain_c = ParaId::from(3_u32); // ensure that we have 5 groups by registering 2 parachains. - schedule_blank_para(chain_a, true); - schedule_blank_para(chain_b, true); - schedule_blank_para(chain_c, false); + schedule_blank_para(chain_a, ParaKind::Parachain); + schedule_blank_para(chain_b, ParaKind::Parachain); + schedule_blank_para(chain_c, ParaKind::Parathread); run_to_block(1, |number| match number { 1 => Some(SessionChangeNotification { @@ -447,13 +447,13 @@ fn schedule_schedules() { assert_eq!(default_config().parathread_cores, 3); // register 2 parachains - schedule_blank_para(chain_a, true); - schedule_blank_para(chain_b, true); + schedule_blank_para(chain_a, ParaKind::Parachain); + schedule_blank_para(chain_b, ParaKind::Parachain); // and 3 parathreads - schedule_blank_para(thread_a, false); - schedule_blank_para(thread_b, false); - schedule_blank_para(thread_c, false); + schedule_blank_para(thread_a, ParaKind::Parathread); + schedule_blank_para(thread_b, ParaKind::Parathread); + schedule_blank_para(thread_c, ParaKind::Parathread); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { @@ -574,15 +574,15 @@ fn schedule_schedules_including_just_freed() { assert_eq!(default_config().parathread_cores, 3); // register 2 parachains - schedule_blank_para(chain_a, true); - schedule_blank_para(chain_b, true); + schedule_blank_para(chain_a, ParaKind::Parachain); + schedule_blank_para(chain_b, ParaKind::Parachain); // and 5 parathreads - schedule_blank_para(thread_a, false); - schedule_blank_para(thread_b, false); - schedule_blank_para(thread_c, false); - schedule_blank_para(thread_d, false); - schedule_blank_para(thread_e, false); + schedule_blank_para(thread_a, ParaKind::Parathread); + schedule_blank_para(thread_b, ParaKind::Parathread); + schedule_blank_para(thread_c, ParaKind::Parathread); + schedule_blank_para(thread_d, ParaKind::Parathread); + schedule_blank_para(thread_e, ParaKind::Parathread); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { @@ -743,9 +743,9 @@ fn schedule_clears_availability_cores() { assert_eq!(default_config().parathread_cores, 3); // register 3 parachains - schedule_blank_para(chain_a, true); - schedule_blank_para(chain_b, true); - schedule_blank_para(chain_c, true); + schedule_blank_para(chain_a, ParaKind::Parachain); + schedule_blank_para(chain_b, ParaKind::Parachain); + schedule_blank_para(chain_c, ParaKind::Parachain); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { @@ -849,8 +849,8 @@ fn schedule_rotates_groups() { new_test_ext(genesis_config).execute_with(|| { assert_eq!(default_config().parathread_cores, 3); - schedule_blank_para(thread_a, false); - schedule_blank_para(thread_b, false); + schedule_blank_para(thread_a, ParaKind::Parathread); + schedule_blank_para(thread_b, ParaKind::Parathread); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { @@ -921,8 +921,8 @@ fn parathread_claims_are_pruned_after_retries() { new_test_ext(genesis_config).execute_with(|| { assert_eq!(default_config().parathread_cores, 3); - schedule_blank_para(thread_a, false); - schedule_blank_para(thread_b, false); + schedule_blank_para(thread_a, ParaKind::Parathread); + schedule_blank_para(thread_b, ParaKind::Parathread); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { @@ -978,8 +978,8 @@ fn availability_predicate_works() { let thread_a = ParaId::from(2_u32); new_test_ext(genesis_config).execute_with(|| { - schedule_blank_para(chain_a, true); - schedule_blank_para(thread_a, false); + schedule_blank_para(chain_a, ParaKind::Parachain); + schedule_blank_para(thread_a, ParaKind::Parathread); // start a new session with our chain & thread registered. run_to_block(1, |number| match number { @@ -1075,8 +1075,8 @@ fn next_up_on_available_uses_next_scheduled_or_none_for_thread() { let collator = CollatorId::from(Sr25519Keyring::Alice.public()); new_test_ext(genesis_config).execute_with(|| { - schedule_blank_para(thread_a, false); - schedule_blank_para(thread_b, false); + schedule_blank_para(thread_a, ParaKind::Parathread); + schedule_blank_para(thread_b, ParaKind::Parathread); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { @@ -1147,8 +1147,8 @@ fn next_up_on_time_out_reuses_claim_if_nothing_queued() { let collator = CollatorId::from(Sr25519Keyring::Alice.public()); new_test_ext(genesis_config).execute_with(|| { - schedule_blank_para(thread_a, false); - schedule_blank_para(thread_b, false); + schedule_blank_para(thread_a, ParaKind::Parathread); + schedule_blank_para(thread_b, ParaKind::Parathread); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { @@ -1222,7 +1222,7 @@ fn next_up_on_available_is_parachain_always() { let chain_a = ParaId::from(1_u32); new_test_ext(genesis_config).execute_with(|| { - schedule_blank_para(chain_a, true); + schedule_blank_para(chain_a, ParaKind::Parachain); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { @@ -1276,7 +1276,7 @@ fn next_up_on_time_out_is_parachain_always() { let chain_a = ParaId::from(1_u32); new_test_ext(genesis_config).execute_with(|| { - schedule_blank_para(chain_a, true); + schedule_blank_para(chain_a, ParaKind::Parachain); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { @@ -1330,8 +1330,8 @@ fn session_change_requires_reschedule_dropping_removed_paras() { let chain_b = ParaId::from(2_u32); // ensure that we have 5 groups by registering 2 parachains. - schedule_blank_para(chain_a, true); - schedule_blank_para(chain_b, true); + schedule_blank_para(chain_a, ParaKind::Parachain); + schedule_blank_para(chain_b, ParaKind::Parachain); run_to_block(1, |number| match number { 1 => Some(SessionChangeNotification { @@ -1409,8 +1409,8 @@ fn parathread_claims_are_pruned_after_deregistration() { new_test_ext(genesis_config).execute_with(|| { assert_eq!(default_config().parathread_cores, 3); - schedule_blank_para(thread_a, false); - schedule_blank_para(thread_b, false); + schedule_blank_para(thread_a, ParaKind::Parathread); + schedule_blank_para(thread_b, ParaKind::Parathread); // start a new session to activate, 5 validators for 5 cores. run_to_block(1, |number| match number { diff --git a/runtime/parachains/src/session_info.rs b/runtime/parachains/src/session_info.rs index c903638423c2..cbd67a200a16 100644 --- a/runtime/parachains/src/session_info.rs +++ b/runtime/parachains/src/session_info.rs @@ -126,12 +126,12 @@ impl Pallet { let dispute_period = config.dispute_period; - let validators = notification.validators.clone(); + let validators = notification.validators.clone().into(); let discovery_keys = ::authorities(); let assignment_keys = AssignmentKeysUnsafe::::get(); let active_set = >::active_validator_indices(); - let validator_groups = >::validator_groups(); + let validator_groups = >::validator_groups().into(); let n_cores = >::availability_cores().len() as u32; let zeroth_delay_tranche_width = config.zeroth_delay_tranche_width; let relay_vrf_modulo_samples = config.relay_vrf_modulo_samples; diff --git a/runtime/parachains/src/session_info/tests.rs b/runtime/parachains/src/session_info/tests.rs index 168bd3d1cc27..7bf68736b572 100644 --- a/runtime/parachains/src/session_info/tests.rs +++ b/runtime/parachains/src/session_info/tests.rs @@ -201,7 +201,7 @@ fn session_info_active_subsets() { }); let session = Sessions::::get(&1).unwrap(); - assert_eq!(session.validators, validators); + assert_eq!(session.validators.to_vec(), validators); assert_eq!( session.discovery_keys, take_active_subset_and_inactive(&active_set, &unscrambled_discovery), diff --git a/runtime/parachains/src/ump.rs b/runtime/parachains/src/ump.rs index 5aa7b17d923c..8d734acb3464 100644 --- a/runtime/parachains/src/ump.rs +++ b/runtime/parachains/src/ump.rs @@ -107,7 +107,7 @@ impl, C: Config> UmpSink VersionedXcm, }; - let id = upward_message_id(&data[..]); + let id = upward_message_id(data); let maybe_msg_and_weight = VersionedXcm::::decode_all_with_depth_limit( xcm::MAX_XCM_DECODE_DEPTH, &mut data, diff --git a/runtime/polkadot/Cargo.toml b/runtime/polkadot/Cargo.toml index c52aeb2a1ec0..3c40ae7f1e4b 100644 --- a/runtime/polkadot/Cargo.toml +++ b/runtime/polkadot/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "polkadot-runtime" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" build = "build.rs" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } @@ -16,73 +16,73 @@ serde_derive = { version = "1.0.117", optional = true } static_assertions = "1.1.0" smallvec = "1.8.0" -authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-npos-elections = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, package = "sp-beefy" , branch = "polkadot-v0.9.36" } +block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-npos-elections = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-bags-list = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-child-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-fast-unstake = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-identity = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-im-online = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-nomination-pools = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking-reward-curve = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-system = {git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-bags-list = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-child-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-fast-unstake = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-identity = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-im-online = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-nomination-pools = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking-reward-curve = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-system = {git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } polkadot-runtime-constants = { package = "polkadot-runtime-constants", path = "./constants", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-tips = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-tips = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } pallet-xcm = { path = "../../xcm/pallet-xcm", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-election-provider-support-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-offences-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-session-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-nomination-pools-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-election-provider-support-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-offences-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-session-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-nomination-pools-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } hex-literal = { version = "0.3.4", optional = true } runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false } @@ -96,16 +96,16 @@ xcm-builder = { package = "xcm-builder", path = "../../xcm/xcm-builder", default [dev-dependencies] hex-literal = "0.3.4" tiny-keccak = { version = "2.0.2", features = ["keccak"] } -keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } serde_json = "1.0.81" separator = "0.4.1" -remote-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -tokio = { version = "1.19.2", features = ["macros"] } -sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +remote-externalities = { git = "https://github.com/paritytech/substrate", package = "frame-remote-externalities" , branch = "polkadot-v0.9.36" } +tokio = { version = "1.22.0", features = ["macros"] } +sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/runtime/polkadot/constants/Cargo.toml b/runtime/polkadot/constants/Cargo.toml index 717be2c5dfa7..e2780e13cc60 100644 --- a/runtime/polkadot/constants/Cargo.toml +++ b/runtime/polkadot/constants/Cargo.toml @@ -1,18 +1,18 @@ [package] name = "polkadot-runtime-constants" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] smallvec = "1.8.0" -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } primitives = { package = "polkadot-primitives", path = "../../../primitives", default-features = false } runtime-common = { package = "polkadot-runtime-common", path = "../../common", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-weights = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/runtime/polkadot/constants/src/weights/block_weights.rs b/runtime/polkadot/constants/src/weights/block_weights.rs index ffe23486689f..f9231434cdaf 100644 --- a/runtime/polkadot/constants/src/weights/block_weights.rs +++ b/runtime/polkadot/constants/src/weights/block_weights.rs @@ -14,7 +14,7 @@ // 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: 2022-10-25 (Y/M/D) +//! DATE: 2022-12-16 (Y/M/D) //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `block`, LONG-NAME: `BlockExecution`, RUNTIME: `Development` @@ -35,23 +35,24 @@ // --header=./file_header.txt use sp_core::parameter_types; -use sp_weights::{constants::WEIGHT_PER_NANOS, Weight}; +use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; parameter_types! { /// Time to execute an empty block. /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 5_724_661, 5_957_728 - /// Average: 5_773_973 - /// Median: 5_766_638 - /// Std-Dev: 41694.64 + /// Min, Max: 5_985_342, 6_305_787 + /// Average: 6_062_818 + /// Median: 6_038_168 + /// Std-Dev: 73457.12 /// /// Percentiles nanoseconds: - /// 99th: 5_903_185 - /// 95th: 5_846_214 - /// 75th: 5_789_579 - pub const BlockExecutionWeight: Weight = WEIGHT_PER_NANOS.saturating_mul(5_773_973); + /// 99th: 6_284_621 + /// 95th: 6_214_705 + /// 75th: 6_089_252 + pub const BlockExecutionWeight: Weight = + Weight::from_ref_time(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(6_062_818)); } #[cfg(test)] @@ -67,12 +68,12 @@ mod test_weights { // At least 100 µs. assert!( - w.ref_time() >= 100u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 100 µs." ); // At most 50 ms. assert!( - w.ref_time() <= 50u64 * constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms." ); } diff --git a/runtime/polkadot/constants/src/weights/extrinsic_weights.rs b/runtime/polkadot/constants/src/weights/extrinsic_weights.rs index 0e0481048e38..67ddbec26837 100644 --- a/runtime/polkadot/constants/src/weights/extrinsic_weights.rs +++ b/runtime/polkadot/constants/src/weights/extrinsic_weights.rs @@ -14,7 +14,7 @@ // 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: 2022-10-25 (Y/M/D) +//! DATE: 2022-12-16 (Y/M/D) //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `extrinsic`, LONG-NAME: `ExtrinsicBase`, RUNTIME: `Development` @@ -35,23 +35,24 @@ // --header=./file_header.txt use sp_core::parameter_types; -use sp_weights::{constants::WEIGHT_PER_NANOS, Weight}; +use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; parameter_types! { /// Time to execute a NO-OP extrinsic, for example `System::remark`. /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 93_411, 94_850 - /// Average: 93_780 - /// Median: 93_708 - /// Std-Dev: 265.55 + /// Min, Max: 97_487, 99_047 + /// Average: 97_884 + /// Median: 97_809 + /// Std-Dev: 317.39 /// /// Percentiles nanoseconds: - /// 99th: 94_619 - /// 95th: 94_334 - /// 75th: 93_854 - pub const ExtrinsicBaseWeight: Weight = WEIGHT_PER_NANOS.saturating_mul(93_780); + /// 99th: 98_875 + /// 95th: 98_689 + /// 75th: 97_943 + pub const ExtrinsicBaseWeight: Weight = + Weight::from_ref_time(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(97_884)); } #[cfg(test)] @@ -67,12 +68,12 @@ mod test_weights { // At least 10 µs. assert!( - w.ref_time() >= 10u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs." ); // At most 1 ms. assert!( - w.ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms." ); } diff --git a/runtime/polkadot/constants/src/weights/paritydb_weights.rs b/runtime/polkadot/constants/src/weights/paritydb_weights.rs index 9695b7bc7800..95c91e5182bd 100644 --- a/runtime/polkadot/constants/src/weights/paritydb_weights.rs +++ b/runtime/polkadot/constants/src/weights/paritydb_weights.rs @@ -57,7 +57,7 @@ pub mod constants { /// 99th: 14_451 /// 95th: 12_588 /// 75th: 11_200 - read: 11_826 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 11_826 * constants::WEIGHT_REF_TIME_PER_NANOS, /// Time to write one storage item. /// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`. @@ -72,7 +72,7 @@ pub mod constants { /// 99th: 69_379 /// 95th: 47_168 /// 75th: 35_252 - write: 38_052 * constants::WEIGHT_PER_NANOS.ref_time(), + write: 38_052 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -88,20 +88,20 @@ pub mod constants { fn bound() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/polkadot/constants/src/weights/rocksdb_weights.rs b/runtime/polkadot/constants/src/weights/rocksdb_weights.rs index 1ed70431b9e3..cfc480ce9461 100644 --- a/runtime/polkadot/constants/src/weights/rocksdb_weights.rs +++ b/runtime/polkadot/constants/src/weights/rocksdb_weights.rs @@ -56,7 +56,7 @@ pub mod constants { /// 99th: 32_074 /// 95th: 26_658 /// 75th: 19_363 - read: 20_499 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 20_499 * constants::WEIGHT_REF_TIME_PER_NANOS, /// Time to write one storage item. /// Calculated by multiplying the *Average* of all values with `1.1` and adding `0`. @@ -71,7 +71,7 @@ pub mod constants { /// 99th: 111_151 /// 95th: 92_666 /// 75th: 80_297 - write: 83_471 * constants::WEIGHT_PER_NANOS.ref_time(), + write: 83_471 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -87,20 +87,20 @@ pub mod constants { fn bound() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/polkadot/src/lib.rs b/runtime/polkadot/src/lib.rs index 02f9fd09d482..24f65a37d2a3 100644 --- a/runtime/polkadot/src/lib.rs +++ b/runtime/polkadot/src/lib.rs @@ -58,6 +58,7 @@ use primitives::v2::{ CoreState, GroupRotationInfo, Hash, Id as ParaId, InboundDownwardMessage, InboundHrmpMessage, Moment, Nonce, OccupiedCoreAssumption, PersistedValidationData, ScrapedOnChainVotes, SessionInfo, Signature, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + LOWEST_PUBLIC_ID, }; use sp_core::OpaqueMetadata; use sp_mmr_primitives as mmr; @@ -113,13 +114,13 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("polkadot"), impl_name: create_runtime_str!("parity-polkadot"), authoring_version: 0, - spec_version: 9310, + spec_version: 9360, impl_version: 0, #[cfg(not(feature = "disable-runtime-api"))] apis: RUNTIME_API_VERSIONS, #[cfg(feature = "disable-runtime-api")] apis: sp_version::create_apis_vec![[]], - transaction_version: 16, + transaction_version: 19, state_version: 0, }; @@ -405,6 +406,9 @@ parameter_types! { /// ... and all of the validators as electable targets. Whilst this is the case, we cannot and /// shall not increase the size of the validator intentions. pub const MaxElectableTargets: u16 = u16::MAX; + /// Setup election pallet to support maximum winners upto 1200. This will mean Staking Pallet + /// cannot have active validators higher than this count. + pub const MaxActiveValidators: u32 = 1200; } generate_solution_type!( @@ -423,6 +427,9 @@ impl onchain::Config for OnChainSeqPhragmen { type Solver = SequentialPhragmen; type DataProvider = Staking; type WeightInfo = weights::frame_election_provider_support::WeightInfo; + type MaxWinners = MaxActiveValidators; + type VotersBound = MaxElectingVoters; + type TargetsBound = MaxElectableTargets; } impl pallet_election_provider_multi_phase::MinerConfig for Runtime { @@ -470,10 +477,15 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type MinerTxPriority = NposSolutionPriority; type DataProvider = Staking; #[cfg(feature = "fast-runtime")] - type Fallback = onchain::UnboundedExecution; + type Fallback = onchain::OnChainExecution; #[cfg(not(feature = "fast-runtime"))] - type Fallback = pallet_election_provider_multi_phase::NoFallback; - type GovernanceFallback = onchain::UnboundedExecution; + type Fallback = frame_election_provider_support::NoElection<( + AccountId, + BlockNumber, + Staking, + MaxActiveValidators, + )>; + type GovernanceFallback = onchain::OnChainExecution; type Solver = SequentialPhragmen< AccountId, pallet_election_provider_multi_phase::SolutionAccuracyOf, @@ -487,6 +499,7 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type WeightInfo = weights::pallet_election_provider_multi_phase::WeightInfo; type MaxElectingVoters = MaxElectingVoters; type MaxElectableTargets = MaxElectableTargets; + type MaxWinners = MaxActiveValidators; } parameter_types! { @@ -521,11 +534,20 @@ pallet_staking_reward_curve::build! { parameter_types! { // Six sessions in an era (24 hours). pub const SessionsPerEra: SessionIndex = prod_or_fast!(6, 1); + // 28 eras for unbonding (28 days). - pub const BondingDuration: sp_staking::EraIndex = 28; - pub const SlashDeferDuration: sp_staking::EraIndex = 27; + pub BondingDuration: sp_staking::EraIndex = prod_or_fast!( + 28, + 28, + "DOT_BONDING_DURATION" + ); + pub SlashDeferDuration: sp_staking::EraIndex = prod_or_fast!( + 27, + 27, + "DOT_SLASH_DEFER_DURATION" + ); pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; - pub const MaxNominatorRewardedPerValidator: u32 = 256; + pub const MaxNominatorRewardedPerValidator: u32 = 512; pub const OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); // 16 pub const MaxNominations: u32 = ::LIMIT as u32; @@ -536,6 +558,34 @@ type SlashCancelOrigin = EitherOfDiverse< pallet_collective::EnsureProportionAtLeast, >; +pub struct EraPayout; +impl pallet_staking::EraPayout for EraPayout { + fn era_payout( + total_staked: Balance, + total_issuance: Balance, + era_duration_millis: u64, + ) -> (Balance, Balance) { + // all para-ids that are not active. + let auctioned_slots = Paras::parachains() + .into_iter() + // all active para-ids that do not belong to a system or common good chain is the number + // of parachains that we should take into account for inflation. + .filter(|i| *i >= LOWEST_PUBLIC_ID) + .count() as u64; + + const MAX_ANNUAL_INFLATION: Perquintill = Perquintill::from_percent(10); + const MILLISECONDS_PER_YEAR: u64 = 1000 * 3600 * 24 * 36525 / 100; + + runtime_common::impls::era_payout( + total_staked, + total_issuance, + MAX_ANNUAL_INFLATION, + Perquintill::from_rational(era_duration_millis, MILLISECONDS_PER_YEAR), + auctioned_slots, + ) + } +} + impl pallet_staking::Config for Runtime { type MaxNominations = MaxNominations; type Currency = Balances; @@ -552,12 +602,12 @@ impl pallet_staking::Config for Runtime { // A super-majority of the council can cancel the slash. type SlashCancelOrigin = SlashCancelOrigin; type SessionInterface = Self; - type EraPayout = pallet_staking::ConvertCurve; + type EraPayout = EraPayout; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = ElectionProviderMultiPhase; - type GenesisElectionProvider = onchain::UnboundedExecution; + type GenesisElectionProvider = onchain::OnChainExecution; type VoterList = VoterList; type TargetList = UseValidatorsMap; type MaxUnlockingChunks = frame_support::traits::ConstU32<32>; @@ -569,13 +619,15 @@ impl pallet_staking::Config for Runtime { impl pallet_fast_unstake::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type DepositCurrency = Balances; + type Currency = Balances; + type BatchSize = frame_support::traits::ConstU32<64>; type Deposit = frame_support::traits::ConstU128<{ UNITS }>; type ControlOrigin = EitherOfDiverse< EnsureRoot, pallet_collective::EnsureProportionAtLeast, >; type WeightInfo = weights::pallet_fast_unstake::WeightInfo; + type Staking = Staking; } parameter_types! { @@ -1018,7 +1070,7 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); - pub const MaxSignatories: u16 = 100; + pub const MaxSignatories: u32 = 100; } impl pallet_multisig::Config for Runtime { @@ -1378,11 +1430,10 @@ parameter_types! { impl pallet_nomination_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type CurrencyBalance = Balance; type RewardCounter = FixedU128; type BalanceToU256 = runtime_common::BalanceToU256; type U256ToBalance = runtime_common::U256ToBalance; - type StakingInterface = Staking; + type Staking = Staking; type PostUnbondingPoolsWindow = frame_support::traits::ConstU32<4>; type MaxMetadataLen = frame_support::traits::ConstU32<256>; // we use the same number of allowed unlocking chunks as with staking. @@ -1547,6 +1598,8 @@ impl Get<&'static str> for StakingMigrationV11OldPallet { } } +pub type Migrations = (); + /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; @@ -1557,15 +1610,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - ( - // "Bound uses of call" - pallet_preimage::migration::v1::Migration, - pallet_scheduler::migration::v3::MigrateToV4, - pallet_democracy::migrations::v1::Migration, - pallet_multisig::migrations::v1::MigrateToV1, - // "Properly migrate weights to v2" - parachains_configuration::migration::v3::MigrateToV3, - ), + Migrations, >; /// The payload being signed in transactions. @@ -1803,53 +1848,31 @@ sp_api::impl_runtime_apis! { } impl mmr::MmrApi for Runtime { - fn generate_proof(_block_number: BlockNumber) - -> Result<(mmr::EncodableOpaqueLeaf, mmr::Proof), mmr::Error> - { - Err(mmr::Error::PalletNotIncluded) - } - - fn verify_proof(_leaf: mmr::EncodableOpaqueLeaf, _proof: mmr::Proof) - -> Result<(), mmr::Error> - { - Err(mmr::Error::PalletNotIncluded) - } - - fn verify_proof_stateless( - _root: Hash, - _leaf: mmr::EncodableOpaqueLeaf, - _proof: mmr::Proof - ) -> Result<(), mmr::Error> { - Err(mmr::Error::PalletNotIncluded) - } - fn mmr_root() -> Result { Err(mmr::Error::PalletNotIncluded) } - fn generate_batch_proof(_block_numbers: Vec) - -> Result<(Vec, mmr::BatchProof), mmr::Error> - { + fn mmr_leaf_count() -> Result { Err(mmr::Error::PalletNotIncluded) } - fn generate_historical_batch_proof( + fn generate_proof( _block_numbers: Vec, - _best_known_block_number: BlockNumber, - ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { + _best_known_block_number: Option, + ) -> Result<(Vec, mmr::Proof), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_batch_proof(_leaves: Vec, _proof: mmr::BatchProof) + fn verify_proof(_leaves: Vec, _proof: mmr::Proof) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_batch_proof_stateless( + fn verify_proof_stateless( _root: Hash, _leaves: Vec, - _proof: mmr::BatchProof + _proof: mmr::Proof ) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } @@ -1989,21 +2012,21 @@ sp_api::impl_runtime_apis! { #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { - fn on_runtime_upgrade() -> (Weight, Weight) { + fn on_runtime_upgrade(checks: bool) -> (Weight, Weight) { log::info!("try-runtime::on_runtime_upgrade polkadot."); - let weight = Executive::try_runtime_upgrade().unwrap(); + let weight = Executive::try_runtime_upgrade(checks).unwrap(); (weight, BlockWeights::get().max_block) } - fn execute_block(block: Block, state_root_check: bool, select: frame_try_runtime::TryStateSelect) -> Weight { - log::info!( - target: "runtime::polkadot", "try-runtime: executing block #{} ({:?}) / root checks: {:?} / sanity-checks: {:?}", - block.header.number, - block.header.hash(), - state_root_check, - select, - ); - Executive::try_execute_block(block, state_root_check, select).expect("try_execute_block failed") + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect, + ) -> Weight { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. + Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() } } @@ -2271,7 +2294,7 @@ mod test { #[cfg(test)] mod multiplier_tests { use super::*; - use frame_support::{dispatch::GetDispatchInfo, traits::OnFinalize}; + use frame_support::{dispatch::DispatchInfo, traits::OnFinalize}; use runtime_common::{MinimumMultiplier, TargetBlockFullness}; use separator::Separatable; use sp_runtime::traits::Convert; @@ -2313,17 +2336,8 @@ mod multiplier_tests { let mut blocks = 0; let mut fees_paid = 0; - let call = frame_system::Call::::fill_block { - ratio: Perbill::from_rational( - block_weight.ref_time(), - BlockWeights::get().get(DispatchClass::Normal).max_total.unwrap().ref_time(), - ), - }; - println!("calling {:?}", call); - let info = call.get_dispatch_info(); - // convert to outer call. - let call = RuntimeCall::System(call); - let len = call.using_encoded(|e| e.len()) as u32; + frame_system::Pallet::::set_block_consumed_resources(Weight::MAX, 0); + let info = DispatchInfo { weight: Weight::MAX, ..Default::default() }; let mut t: sp_io::TestExternalities = frame_system::GenesisConfig::default() .build_storage::() @@ -2337,7 +2351,7 @@ mod multiplier_tests { while multiplier <= Multiplier::from_u32(1) { t.execute_with(|| { // imagine this tx was called. - let fee = TransactionPayment::compute_fee(len, &info, 0); + let fee = TransactionPayment::compute_fee(0, &info, 0); fees_paid += fee; // this will update the multiplier. @@ -2424,6 +2438,6 @@ mod remote_tests { .build() .await .unwrap(); - ext.execute_with(|| Runtime::on_runtime_upgrade()); + ext.execute_with(|| Runtime::on_runtime_upgrade(true)); } } diff --git a/runtime/polkadot/src/weights/frame_benchmarking_baseline.rs b/runtime/polkadot/src/weights/frame_benchmarking_baseline.rs index 92a81015d98b..eb6fb793f33c 100644 --- a/runtime/polkadot/src/weights/frame_benchmarking_baseline.rs +++ b/runtime/polkadot/src/weights/frame_benchmarking_baseline.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_benchmarking::baseline` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -46,52 +46,52 @@ pub struct WeightInfo(PhantomData); impl frame_benchmarking::baseline::WeightInfo for WeightInfo { /// The range of component `i` is `[0, 1000000]`. fn addition(_i: u32, ) -> Weight { - // Minimum execution time: 90 nanoseconds. - Weight::from_ref_time(115_922 as u64) + // Minimum execution time: 127 nanoseconds. + Weight::from_ref_time(161_011) } /// The range of component `i` is `[0, 1000000]`. fn subtraction(_i: u32, ) -> Weight { - // Minimum execution time: 95 nanoseconds. - Weight::from_ref_time(122_150 as u64) + // Minimum execution time: 125 nanoseconds. + Weight::from_ref_time(166_605) } /// The range of component `i` is `[0, 1000000]`. fn multiplication(_i: u32, ) -> Weight { - // Minimum execution time: 100 nanoseconds. - Weight::from_ref_time(122_417 as u64) + // Minimum execution time: 121 nanoseconds. + Weight::from_ref_time(156_392) } /// The range of component `i` is `[0, 1000000]`. fn division(_i: u32, ) -> Weight { - // Minimum execution time: 94 nanoseconds. - Weight::from_ref_time(113_684 as u64) + // Minimum execution time: 115 nanoseconds. + Weight::from_ref_time(158_966) } /// The range of component `i` is `[0, 100]`. fn hashing(_i: u32, ) -> Weight { - // Minimum execution time: 18_993_431 nanoseconds. - Weight::from_ref_time(19_437_135_598 as u64) + // Minimum execution time: 20_174_737 nanoseconds. + Weight::from_ref_time(20_470_069_016) } /// The range of component `i` is `[0, 100]`. fn sr25519_verification(i: u32, ) -> Weight { - // Minimum execution time: 109 nanoseconds. - Weight::from_ref_time(442_381 as u64) - // Standard Error: 16_514 - .saturating_add(Weight::from_ref_time(47_391_423 as u64).saturating_mul(i as u64)) + // Minimum execution time: 152 nanoseconds. + Weight::from_ref_time(186_000) + // Standard Error: 10_605 + .saturating_add(Weight::from_ref_time(47_088_039).saturating_mul(i.into())) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn storage_read(i: u32, ) -> Weight { - // Minimum execution time: 112 nanoseconds. - Weight::from_ref_time(117_000 as u64) - // Standard Error: 3_518 - .saturating_add(Weight::from_ref_time(1_822_376 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 138 nanoseconds. + Weight::from_ref_time(155_000) + // Standard Error: 4_456 + .saturating_add(Weight::from_ref_time(1_940_845).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn storage_write(i: u32, ) -> Weight { - // Minimum execution time: 97 nanoseconds. - Weight::from_ref_time(106_000 as u64) - // Standard Error: 803 - .saturating_add(Weight::from_ref_time(317_931 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 156 nanoseconds. + Weight::from_ref_time(166_000) + // Standard Error: 822 + .saturating_add(Weight::from_ref_time(343_137).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } } diff --git a/runtime/polkadot/src/weights/frame_election_provider_support.rs b/runtime/polkadot/src/weights/frame_election_provider_support.rs index 95149f13a83a..b8e82d973295 100644 --- a/runtime/polkadot/src/weights/frame_election_provider_support.rs +++ b/runtime/polkadot/src/weights/frame_election_provider_support.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_election_provider_support` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -48,22 +48,22 @@ impl frame_election_provider_support::WeightInfo for We /// The range of component `t` is `[500, 1000]`. /// The range of component `d` is `[5, 16]`. fn phragmen(v: u32, _t: u32, d: u32, ) -> Weight { - // Minimum execution time: 5_430_677 nanoseconds. - Weight::from_ref_time(5_464_877_000 as u64) - // Standard Error: 136_164 - .saturating_add(Weight::from_ref_time(5_537_233 as u64).saturating_mul(v as u64)) - // Standard Error: 13_920_972 - .saturating_add(Weight::from_ref_time(1_533_450_990 as u64).saturating_mul(d as u64)) + // Minimum execution time: 5_779_497 nanoseconds. + Weight::from_ref_time(5_840_231_000) + // Standard Error: 137_577 + .saturating_add(Weight::from_ref_time(5_645_822).saturating_mul(v.into())) + // Standard Error: 14_065_464 + .saturating_add(Weight::from_ref_time(1_531_225_802).saturating_mul(d.into())) } /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `d` is `[5, 16]`. fn phragmms(v: u32, _t: u32, d: u32, ) -> Weight { - // Minimum execution time: 4_281_157 nanoseconds. - Weight::from_ref_time(4_309_020_000 as u64) - // Standard Error: 145_954 - .saturating_add(Weight::from_ref_time(5_463_106 as u64).saturating_mul(v as u64)) - // Standard Error: 14_921_849 - .saturating_add(Weight::from_ref_time(1_772_340_546 as u64).saturating_mul(d as u64)) + // Minimum execution time: 4_463_683 nanoseconds. + Weight::from_ref_time(4_491_123_000) + // Standard Error: 145_041 + .saturating_add(Weight::from_ref_time(5_493_161).saturating_mul(v.into())) + // Standard Error: 14_828_496 + .saturating_add(Weight::from_ref_time(1_744_510_977).saturating_mul(d.into())) } } diff --git a/runtime/polkadot/src/weights/frame_system.rs b/runtime/polkadot/src/weights/frame_system.rs index 1ad8c7e3ea02..01716c75602e 100644 --- a/runtime/polkadot/src/weights/frame_system.rs +++ b/runtime/polkadot/src/weights/frame_system.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_system` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -46,51 +46,51 @@ pub struct WeightInfo(PhantomData); impl frame_system::WeightInfo for WeightInfo { /// The range of component `b` is `[0, 3932160]`. fn remark(b: u32, ) -> Weight { - // Minimum execution time: 2_963 nanoseconds. - Weight::from_ref_time(3_019_000 as u64) + // Minimum execution time: 3_586 nanoseconds. + Weight::from_ref_time(13_110_218) // Standard Error: 0 - .saturating_add(Weight::from_ref_time(409 as u64).saturating_mul(b as u64)) + .saturating_add(Weight::from_ref_time(406).saturating_mul(b.into())) } /// The range of component `b` is `[0, 3932160]`. fn remark_with_event(b: u32, ) -> Weight { - // Minimum execution time: 11_944 nanoseconds. - Weight::from_ref_time(12_024_000 as u64) + // Minimum execution time: 12_595 nanoseconds. + Weight::from_ref_time(12_730_000) // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_718 as u64).saturating_mul(b as u64)) + .saturating_add(Weight::from_ref_time(1_758).saturating_mul(b.into())) } // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - // Minimum execution time: 7_391 nanoseconds. - Weight::from_ref_time(7_747_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 8_399 nanoseconds. + Weight::from_ref_time(8_641_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { - // Minimum execution time: 3_096 nanoseconds. - Weight::from_ref_time(3_168_000 as u64) - // Standard Error: 2_366 - .saturating_add(Weight::from_ref_time(607_856 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 3_517 nanoseconds. + Weight::from_ref_time(3_591_000) + // Standard Error: 2_238 + .saturating_add(Weight::from_ref_time(629_071).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { - // Minimum execution time: 3_088 nanoseconds. - Weight::from_ref_time(3_190_000 as u64) - // Standard Error: 893 - .saturating_add(Weight::from_ref_time(434_445 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 3_574 nanoseconds. + Weight::from_ref_time(3_709_000) + // Standard Error: 907 + .saturating_add(Weight::from_ref_time(448_713).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { - // Minimum execution time: 4_592 nanoseconds. - Weight::from_ref_time(4_633_000 as u64) - // Standard Error: 1_146 - .saturating_add(Weight::from_ref_time(928_996 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 5_308 nanoseconds. + Weight::from_ref_time(5_374_000) + // Standard Error: 1_138 + .saturating_add(Weight::from_ref_time(964_567).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } } diff --git a/runtime/polkadot/src/weights/pallet_bags_list.rs b/runtime/polkadot/src/weights/pallet_bags_list.rs index e02009f6b6e4..8d797ee07a58 100644 --- a/runtime/polkadot/src/weights/pallet_bags_list.rs +++ b/runtime/polkadot/src/weights/pallet_bags_list.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_bags_list` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -49,20 +49,20 @@ impl pallet_bags_list::WeightInfo for WeightInfo { // Storage: VoterList ListNodes (r:4 w:4) // Storage: VoterList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - // Minimum execution time: 59_212 nanoseconds. - Weight::from_ref_time(59_911_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 64_110 nanoseconds. + Weight::from_ref_time(64_658_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - // Minimum execution time: 59_706 nanoseconds. - Weight::from_ref_time(60_434_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 63_175 nanoseconds. + Weight::from_ref_time(64_129_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: VoterList ListNodes (r:4 w:4) // Storage: Staking Bonded (r:2 w:0) @@ -70,9 +70,9 @@ impl pallet_bags_list::WeightInfo for WeightInfo { // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: VoterList ListBags (r:1 w:1) fn put_in_front_of() -> Weight { - // Minimum execution time: 59_346 nanoseconds. - Weight::from_ref_time(60_037_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 61_345 nanoseconds. + Weight::from_ref_time(62_203_000) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(6)) } } diff --git a/runtime/polkadot/src/weights/pallet_balances.rs b/runtime/polkadot/src/weights/pallet_balances.rs index aa55f9b76dd0..732069468749 100644 --- a/runtime/polkadot/src/weights/pallet_balances.rs +++ b/runtime/polkadot/src/weights/pallet_balances.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -46,51 +46,51 @@ pub struct WeightInfo(PhantomData); impl pallet_balances::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - // Minimum execution time: 38_197 nanoseconds. - Weight::from_ref_time(39_286_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 41_890 nanoseconds. + Weight::from_ref_time(42_503_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - // Minimum execution time: 28_875 nanoseconds. - Weight::from_ref_time(29_367_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 31_707 nanoseconds. + Weight::from_ref_time(32_868_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - // Minimum execution time: 21_697 nanoseconds. - Weight::from_ref_time(22_248_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 24_009 nanoseconds. + Weight::from_ref_time(24_304_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - // Minimum execution time: 24_515 nanoseconds. - Weight::from_ref_time(25_094_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_784 nanoseconds. + Weight::from_ref_time(27_316_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:2 w:2) fn force_transfer() -> Weight { - // Minimum execution time: 38_293 nanoseconds. - Weight::from_ref_time(38_972_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 42_356 nanoseconds. + Weight::from_ref_time(43_112_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - // Minimum execution time: 33_997 nanoseconds. - Weight::from_ref_time(34_619_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 37_615 nanoseconds. + Weight::from_ref_time(38_059_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - // Minimum execution time: 18_917 nanoseconds. - Weight::from_ref_time(19_358_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 21_319 nanoseconds. + Weight::from_ref_time(21_831_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/pallet_bounties.rs b/runtime/polkadot/src/weights/pallet_bounties.rs index b1f502e179bc..a43d75ec2823 100644 --- a/runtime/polkadot/src/weights/pallet_bounties.rs +++ b/runtime/polkadot/src/weights/pallet_bounties.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_bounties` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -50,101 +50,59 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Storage: Bounties Bounties (r:0 w:1) /// The range of component `d` is `[0, 16384]`. fn propose_bounty(d: u32, ) -> Weight { - // Minimum execution time: 27_752 nanoseconds. - Weight::from_ref_time(29_022_492 as u64) - // Standard Error: 9 - .saturating_add(Weight::from_ref_time(799 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 29_384 nanoseconds. + Weight::from_ref_time(31_061_881) + // Standard Error: 7 + .saturating_add(Weight::from_ref_time(819).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) - // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - // Minimum execution time: 11_725 nanoseconds. - Weight::from_ref_time(11_880_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - // Minimum execution time: 10_693 nanoseconds. - Weight::from_ref_time(11_112_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - // Minimum execution time: 38_901 nanoseconds. - Weight::from_ref_time(39_518_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - // Minimum execution time: 27_039 nanoseconds. - Weight::from_ref_time(27_547_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: ChildBounties ParentChildBounties (r:1 w:0) fn award_bounty() -> Weight { - // Minimum execution time: 23_046 nanoseconds. - Weight::from_ref_time(23_499_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: System Account (r:3 w:3) - // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - // Minimum execution time: 66_013 nanoseconds. - Weight::from_ref_time(67_696_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } // Storage: Bounties Bounties (r:1 w:1) // Storage: ChildBounties ParentChildBounties (r:1 w:0) // Storage: System Account (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - // Minimum execution time: 41_852 nanoseconds. - Weight::from_ref_time(42_274_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 45_583 nanoseconds. + Weight::from_ref_time(46_179_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: ChildBounties ParentChildBounties (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - // Minimum execution time: 51_433 nanoseconds. - Weight::from_ref_time(52_097_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - // Minimum execution time: 20_562 nanoseconds. - Weight::from_ref_time(20_973_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } // Storage: Bounties BountyApprovals (r:1 w:1) - // Storage: Bounties Bounties (r:2 w:2) - // Storage: System Account (r:4 w:4) /// The range of component `b` is `[0, 100]`. - fn spend_funds(b: u32, ) -> Weight { - // Minimum execution time: 6_980 nanoseconds. - Weight::from_ref_time(9_837_399 as u64) - // Standard Error: 20_050 - .saturating_add(Weight::from_ref_time(24_678_056 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(b as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(b as u64))) + fn spend_funds(_b: u32, ) -> Weight { + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(3_372_666) } } diff --git a/runtime/polkadot/src/weights/pallet_child_bounties.rs b/runtime/polkadot/src/weights/pallet_child_bounties.rs index 3a5ec2f9b11f..be0058e1f9d2 100644 --- a/runtime/polkadot/src/weights/pallet_child_bounties.rs +++ b/runtime/polkadot/src/weights/pallet_child_bounties.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_child_bounties` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -44,88 +44,37 @@ use sp_std::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) - // Storage: Bounties Bounties (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: ChildBounties ChildBountyCount (r:1 w:1) - // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - // Storage: ChildBounties ChildBounties (r:0 w:1) /// The range of component `d` is `[0, 16384]`. - fn add_child_bounty(d: u32, ) -> Weight { - // Minimum execution time: 49_044 nanoseconds. - Weight::from_ref_time(50_308_289 as u64) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(783 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + fn add_child_bounty(_d: u32, ) -> Weight { + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) fn propose_curator() -> Weight { - // Minimum execution time: 17_933 nanoseconds. - Weight::from_ref_time(18_741_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - // Minimum execution time: 31_905 nanoseconds. - Weight::from_ref_time(32_602_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: Bounties Bounties (r:1 w:0) - // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - // Minimum execution time: 43_592 nanoseconds. - Weight::from_ref_time(44_161_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) fn award_child_bounty() -> Weight { - // Minimum execution time: 26_698 nanoseconds. - Weight::from_ref_time(27_014_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: System Account (r:3 w:3) - // Storage: ChildBounties ParentChildBounties (r:1 w:1) - // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn claim_child_bounty() -> Weight { - // Minimum execution time: 65_588 nanoseconds. - Weight::from_ref_time(66_068_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - // Storage: ChildBounties ParentChildBounties (r:1 w:1) - // Storage: System Account (r:2 w:2) - // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_added() -> Weight { - // Minimum execution time: 48_802 nanoseconds. - Weight::from_ref_time(49_236_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: System Account (r:3 w:3) - // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - // Storage: ChildBounties ParentChildBounties (r:1 w:1) - // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_active() -> Weight { - // Minimum execution time: 58_165 nanoseconds. - Weight::from_ref_time(58_828_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } } diff --git a/runtime/polkadot/src/weights/pallet_collective_council.rs b/runtime/polkadot/src/weights/pallet_collective_council.rs index 0251f55cb6ca..5f9b20fd819c 100644 --- a/runtime/polkadot/src/weights/pallet_collective_council.rs +++ b/runtime/polkadot/src/weights/pallet_collective_council.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -55,80 +55,80 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 16_559 nanoseconds. - Weight::from_ref_time(16_803_000 as u64) - // Standard Error: 46_979 - .saturating_add(Weight::from_ref_time(5_411_495 as u64).saturating_mul(m as u64)) - // Standard Error: 46_979 - .saturating_add(Weight::from_ref_time(7_379_659 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 17_297 nanoseconds. + Weight::from_ref_time(17_458_000) + // Standard Error: 46_157 + .saturating_add(Weight::from_ref_time(5_270_521).saturating_mul(m.into())) + // Standard Error: 46_157 + .saturating_add(Weight::from_ref_time(7_355_366).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } // Storage: Council Members (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 18_843 nanoseconds. - Weight::from_ref_time(18_477_543 as u64) - // Standard Error: 34 - .saturating_add(Weight::from_ref_time(1_767 as u64).saturating_mul(b as u64)) - // Standard Error: 360 - .saturating_add(Weight::from_ref_time(12_265 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 20_456 nanoseconds. + Weight::from_ref_time(19_967_863) + // Standard Error: 52 + .saturating_add(Weight::from_ref_time(1_865).saturating_mul(b.into())) + // Standard Error: 540 + .saturating_add(Weight::from_ref_time(14_260).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 20_542 nanoseconds. - Weight::from_ref_time(19_952_992 as u64) - // Standard Error: 24 - .saturating_add(Weight::from_ref_time(1_708 as u64).saturating_mul(b as u64)) - // Standard Error: 253 - .saturating_add(Weight::from_ref_time(23_664 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) + // Minimum execution time: 22_889 nanoseconds. + Weight::from_ref_time(21_861_521) + // Standard Error: 27 + .saturating_add(Weight::from_ref_time(1_773).saturating_mul(b.into())) + // Standard Error: 285 + .saturating_add(Weight::from_ref_time(24_222).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalCount (r:1 w:1) // Storage: Council Voting (r:0 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 26_525 nanoseconds. - Weight::from_ref_time(26_095_210 as u64) - // Standard Error: 65 - .saturating_add(Weight::from_ref_time(3_546 as u64).saturating_mul(b as u64)) - // Standard Error: 679 - .saturating_add(Weight::from_ref_time(21_644 as u64).saturating_mul(m as u64)) - // Standard Error: 670 - .saturating_add(Weight::from_ref_time(108_657 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 28_612 nanoseconds. + Weight::from_ref_time(29_675_084) + // Standard Error: 69 + .saturating_add(Weight::from_ref_time(2_993).saturating_mul(b.into())) + // Standard Error: 730 + .saturating_add(Weight::from_ref_time(21_054).saturating_mul(m.into())) + // Standard Error: 720 + .saturating_add(Weight::from_ref_time(111_187).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Council Members (r:1 w:0) // Storage: Council Voting (r:1 w:1) /// The range of component `m` is `[5, 100]`. /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { - // Minimum execution time: 25_960 nanoseconds. - Weight::from_ref_time(27_053_792 as u64) - // Standard Error: 417 - .saturating_add(Weight::from_ref_time(36_479 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_110 nanoseconds. + Weight::from_ref_time(30_372_451) + // Standard Error: 550 + .saturating_add(Weight::from_ref_time(38_411).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) @@ -139,36 +139,36 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 28_862 nanoseconds. - Weight::from_ref_time(31_105_191 as u64) - // Standard Error: 505 - .saturating_add(Weight::from_ref_time(22_024 as u64).saturating_mul(m as u64)) - // Standard Error: 493 - .saturating_add(Weight::from_ref_time(82_056 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 31_156 nanoseconds. + Weight::from_ref_time(33_782_137) + // Standard Error: 553 + .saturating_add(Weight::from_ref_time(19_185).saturating_mul(m.into())) + // Standard Error: 539 + .saturating_add(Weight::from_ref_time(93_950).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 38_616 nanoseconds. - Weight::from_ref_time(38_991_996 as u64) - // Standard Error: 57 - .saturating_add(Weight::from_ref_time(1_897 as u64).saturating_mul(b as u64)) - // Standard Error: 613 - .saturating_add(Weight::from_ref_time(25_955 as u64).saturating_mul(m as u64)) - // Standard Error: 597 - .saturating_add(Weight::from_ref_time(98_694 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 41_889 nanoseconds. + Weight::from_ref_time(42_988_858) + // Standard Error: 60 + .saturating_add(Weight::from_ref_time(2_041).saturating_mul(b.into())) + // Standard Error: 642 + .saturating_add(Weight::from_ref_time(13_836).saturating_mul(m.into())) + // Standard Error: 625 + .saturating_add(Weight::from_ref_time(114_168).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) @@ -180,37 +180,37 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { - // Minimum execution time: 32_082 nanoseconds. - Weight::from_ref_time(33_158_636 as u64) - // Standard Error: 466 - .saturating_add(Weight::from_ref_time(25_605 as u64).saturating_mul(m as u64)) - // Standard Error: 454 - .saturating_add(Weight::from_ref_time(82_085 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 34_461 nanoseconds. + Weight::from_ref_time(35_613_879) + // Standard Error: 486 + .saturating_add(Weight::from_ref_time(24_091).saturating_mul(m.into())) + // Standard Error: 474 + .saturating_add(Weight::from_ref_time(98_392).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) // Storage: Council Prime (r:1 w:0) // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 40_968 nanoseconds. - Weight::from_ref_time(41_242_466 as u64) - // Standard Error: 60 - .saturating_add(Weight::from_ref_time(1_955 as u64).saturating_mul(b as u64)) - // Standard Error: 640 - .saturating_add(Weight::from_ref_time(24_889 as u64).saturating_mul(m as u64)) - // Standard Error: 624 - .saturating_add(Weight::from_ref_time(99_929 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 43_673 nanoseconds. + Weight::from_ref_time(45_542_514) + // Standard Error: 63 + .saturating_add(Weight::from_ref_time(1_823).saturating_mul(b.into())) + // Standard Error: 673 + .saturating_add(Weight::from_ref_time(12_516).saturating_mul(m.into())) + // Standard Error: 656 + .saturating_add(Weight::from_ref_time(114_430).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Proposals (r:1 w:1) // Storage: Council Voting (r:0 w:1) @@ -218,11 +218,11 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `p` is `[1, 100]`. /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { - // Minimum execution time: 17_891 nanoseconds. - Weight::from_ref_time(21_059_063 as u64) - // Standard Error: 662 - .saturating_add(Weight::from_ref_time(92_982 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 19_493 nanoseconds. + Weight::from_ref_time(22_951_493) + // Standard Error: 699 + .saturating_add(Weight::from_ref_time(98_481).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/polkadot/src/weights/pallet_collective_technical_committee.rs b/runtime/polkadot/src/weights/pallet_collective_technical_committee.rs index 35adf5db0fa6..8739f1ea3eca 100644 --- a/runtime/polkadot/src/weights/pallet_collective_technical_committee.rs +++ b/runtime/polkadot/src/weights/pallet_collective_technical_committee.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -55,80 +55,80 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 16_672 nanoseconds. - Weight::from_ref_time(16_894_000 as u64) - // Standard Error: 46_829 - .saturating_add(Weight::from_ref_time(5_355_665 as u64).saturating_mul(m as u64)) - // Standard Error: 46_829 - .saturating_add(Weight::from_ref_time(7_426_019 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 17_842 nanoseconds. + Weight::from_ref_time(18_147_000) + // Standard Error: 44_575 + .saturating_add(Weight::from_ref_time(5_076_503).saturating_mul(m.into())) + // Standard Error: 44_575 + .saturating_add(Weight::from_ref_time(7_287_051).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } // Storage: TechnicalCommittee Members (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 19_220 nanoseconds. - Weight::from_ref_time(18_726_422 as u64) - // Standard Error: 35 - .saturating_add(Weight::from_ref_time(1_756 as u64).saturating_mul(b as u64)) - // Standard Error: 368 - .saturating_add(Weight::from_ref_time(12_959 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 21_266 nanoseconds. + Weight::from_ref_time(20_575_000) + // Standard Error: 71 + .saturating_add(Weight::from_ref_time(1_862).saturating_mul(b.into())) + // Standard Error: 739 + .saturating_add(Weight::from_ref_time(13_889).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 20_968 nanoseconds. - Weight::from_ref_time(20_449_941 as u64) - // Standard Error: 23 - .saturating_add(Weight::from_ref_time(1_776 as u64).saturating_mul(b as u64)) - // Standard Error: 242 - .saturating_add(Weight::from_ref_time(22_714 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) + // Minimum execution time: 23_594 nanoseconds. + Weight::from_ref_time(22_443_580) + // Standard Error: 25 + .saturating_add(Weight::from_ref_time(1_886).saturating_mul(b.into())) + // Standard Error: 258 + .saturating_add(Weight::from_ref_time(22_696).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) } // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:1) // Storage: TechnicalCommittee ProposalCount (r:1 w:1) // Storage: TechnicalCommittee Voting (r:0 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 27_344 nanoseconds. - Weight::from_ref_time(27_254_179 as u64) - // Standard Error: 61 - .saturating_add(Weight::from_ref_time(3_575 as u64).saturating_mul(b as u64)) - // Standard Error: 637 - .saturating_add(Weight::from_ref_time(18_357 as u64).saturating_mul(m as u64)) - // Standard Error: 629 - .saturating_add(Weight::from_ref_time(114_724 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 29_664 nanoseconds. + Weight::from_ref_time(30_590_145) + // Standard Error: 62 + .saturating_add(Weight::from_ref_time(3_330).saturating_mul(b.into())) + // Standard Error: 656 + .saturating_add(Weight::from_ref_time(19_122).saturating_mul(m.into())) + // Standard Error: 648 + .saturating_add(Weight::from_ref_time(117_965).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee Voting (r:1 w:1) /// The range of component `m` is `[5, 100]`. /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { - // Minimum execution time: 27_321 nanoseconds. - Weight::from_ref_time(28_666_629 as u64) - // Standard Error: 486 - .saturating_add(Weight::from_ref_time(39_409 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_790 nanoseconds. + Weight::from_ref_time(31_060_640) + // Standard Error: 478 + .saturating_add(Weight::from_ref_time(40_001).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) @@ -139,36 +139,36 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 30_522 nanoseconds. - Weight::from_ref_time(31_888_685 as u64) - // Standard Error: 445 - .saturating_add(Weight::from_ref_time(21_903 as u64).saturating_mul(m as u64)) - // Standard Error: 434 - .saturating_add(Weight::from_ref_time(81_600 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 32_701 nanoseconds. + Weight::from_ref_time(34_343_347) + // Standard Error: 450 + .saturating_add(Weight::from_ref_time(19_598).saturating_mul(m.into())) + // Standard Error: 438 + .saturating_add(Weight::from_ref_time(94_021).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 39_694 nanoseconds. - Weight::from_ref_time(39_895_326 as u64) - // Standard Error: 53 - .saturating_add(Weight::from_ref_time(1_748 as u64).saturating_mul(b as u64)) - // Standard Error: 562 - .saturating_add(Weight::from_ref_time(23_990 as u64).saturating_mul(m as u64)) - // Standard Error: 548 - .saturating_add(Weight::from_ref_time(98_021 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 42_819 nanoseconds. + Weight::from_ref_time(43_537_489) + // Standard Error: 57 + .saturating_add(Weight::from_ref_time(1_956).saturating_mul(b.into())) + // Standard Error: 605 + .saturating_add(Weight::from_ref_time(16_062).saturating_mul(m.into())) + // Standard Error: 589 + .saturating_add(Weight::from_ref_time(113_768).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) @@ -180,37 +180,37 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { - // Minimum execution time: 32_817 nanoseconds. - Weight::from_ref_time(33_690_970 as u64) - // Standard Error: 459 - .saturating_add(Weight::from_ref_time(26_971 as u64).saturating_mul(m as u64)) - // Standard Error: 447 - .saturating_add(Weight::from_ref_time(82_860 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 35_308 nanoseconds. + Weight::from_ref_time(36_407_551) + // Standard Error: 442 + .saturating_add(Weight::from_ref_time(23_551).saturating_mul(m.into())) + // Standard Error: 431 + .saturating_add(Weight::from_ref_time(96_416).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee Prime (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 41_611 nanoseconds. - Weight::from_ref_time(42_243_655 as u64) - // Standard Error: 54 - .saturating_add(Weight::from_ref_time(1_702 as u64).saturating_mul(b as u64)) - // Standard Error: 580 - .saturating_add(Weight::from_ref_time(23_529 as u64).saturating_mul(m as u64)) - // Standard Error: 565 - .saturating_add(Weight::from_ref_time(98_033 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 44_569 nanoseconds. + Weight::from_ref_time(45_689_468) + // Standard Error: 57 + .saturating_add(Weight::from_ref_time(1_998).saturating_mul(b.into())) + // Standard Error: 605 + .saturating_add(Weight::from_ref_time(15_421).saturating_mul(m.into())) + // Standard Error: 590 + .saturating_add(Weight::from_ref_time(115_962).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Proposals (r:1 w:1) // Storage: TechnicalCommittee Voting (r:0 w:1) @@ -218,11 +218,11 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `p` is `[1, 100]`. /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { - // Minimum execution time: 18_237 nanoseconds. - Weight::from_ref_time(21_495_420 as u64) - // Standard Error: 708 - .saturating_add(Weight::from_ref_time(96_658 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 20_107 nanoseconds. + Weight::from_ref_time(23_313_947) + // Standard Error: 654 + .saturating_add(Weight::from_ref_time(102_256).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/polkadot/src/weights/pallet_democracy.rs b/runtime/polkadot/src/weights/pallet_democracy.rs index 425a4b7cd961..9f5b50e646be 100644 --- a/runtime/polkadot/src/weights/pallet_democracy.rs +++ b/runtime/polkadot/src/weights/pallet_democracy.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_democracy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -49,43 +49,43 @@ impl pallet_democracy::WeightInfo for WeightInfo { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - // Minimum execution time: 42_035 nanoseconds. - Weight::from_ref_time(42_673_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 44_610 nanoseconds. + Weight::from_ref_time(45_204_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy DepositOf (r:1 w:1) fn second() -> Weight { - // Minimum execution time: 37_908 nanoseconds. - Weight::from_ref_time(39_524_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 40_153 nanoseconds. + Weight::from_ref_time(41_771_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new() -> Weight { - // Minimum execution time: 48_027 nanoseconds. - Weight::from_ref_time(48_672_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 51_249 nanoseconds. + Weight::from_ref_time(51_813_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing() -> Weight { - // Minimum execution time: 48_623 nanoseconds. - Weight::from_ref_time(49_248_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 51_758 nanoseconds. + Weight::from_ref_time(52_106_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - // Minimum execution time: 19_752 nanoseconds. - Weight::from_ref_time(20_235_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 21_407 nanoseconds. + Weight::from_ref_time(21_908_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy PublicProps (r:1 w:1) // Storage: Democracy DepositOf (r:1 w:1) @@ -94,75 +94,75 @@ impl pallet_democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Blacklist (r:0 w:1) fn blacklist() -> Weight { - // Minimum execution time: 75_593 nanoseconds. - Weight::from_ref_time(76_707_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 80_197 nanoseconds. + Weight::from_ref_time(81_497_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose() -> Weight { - // Minimum execution time: 15_433 nanoseconds. - Weight::from_ref_time(15_751_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 16_835 nanoseconds. + Weight::from_ref_time(17_357_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - // Minimum execution time: 4_187 nanoseconds. - Weight::from_ref_time(4_344_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_757 nanoseconds. + Weight::from_ref_time(5_025_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - // Minimum execution time: 4_424 nanoseconds. - Weight::from_ref_time(4_522_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_719 nanoseconds. + Weight::from_ref_time(5_036_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - // Minimum execution time: 18_919 nanoseconds. - Weight::from_ref_time(19_574_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 20_986 nanoseconds. + Weight::from_ref_time(21_256_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external() -> Weight { - // Minimum execution time: 24_749 nanoseconds. - Weight::from_ref_time(25_443_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 26_708 nanoseconds. + Weight::from_ref_time(27_404_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy PublicProps (r:1 w:1) // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn cancel_proposal() -> Weight { - // Minimum execution time: 63_025 nanoseconds. - Weight::from_ref_time(64_438_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 67_797 nanoseconds. + Weight::from_ref_time(69_032_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - // Minimum execution time: 12_754 nanoseconds. - Weight::from_ref_time(13_249_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 14_179 nanoseconds. + Weight::from_ref_time(14_456_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:2 w:0) /// The range of component `r` is `[0, 99]`. fn on_initialize_base(r: u32, ) -> Weight { - // Minimum execution time: 6_036 nanoseconds. - Weight::from_ref_time(9_221_096 as u64) - // Standard Error: 3_753 - .saturating_add(Weight::from_ref_time(2_068_013 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 6_410 nanoseconds. + Weight::from_ref_time(9_082_378) + // Standard Error: 4_425 + .saturating_add(Weight::from_ref_time(2_094_526).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) @@ -172,91 +172,91 @@ impl pallet_democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumInfoOf (r:2 w:0) /// The range of component `r` is `[0, 99]`. fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - // Minimum execution time: 8_435 nanoseconds. - Weight::from_ref_time(11_539_062 as u64) - // Standard Error: 3_966 - .saturating_add(Weight::from_ref_time(2_069_630 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_539 nanoseconds. + Weight::from_ref_time(11_763_633) + // Standard Error: 3_731 + .saturating_add(Weight::from_ref_time(2_106_290).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy VotingOf (r:3 w:3) // Storage: Balances Locks (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:2 w:2) /// The range of component `r` is `[0, 99]`. fn delegate(r: u32, ) -> Weight { - // Minimum execution time: 39_949 nanoseconds. - Weight::from_ref_time(46_035_539 as u64) - // Standard Error: 5_044 - .saturating_add(Weight::from_ref_time(2_971_650 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64))) + // Minimum execution time: 43_180 nanoseconds. + Weight::from_ref_time(49_863_426) + // Standard Error: 6_336 + .saturating_add(Weight::from_ref_time(3_028_333).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((1_u64).saturating_mul(r.into()))) } // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:2 w:2) /// The range of component `r` is `[0, 99]`. fn undelegate(r: u32, ) -> Weight { - // Minimum execution time: 23_826 nanoseconds. - Weight::from_ref_time(27_032_402 as u64) - // Standard Error: 4_525 - .saturating_add(Weight::from_ref_time(2_958_429 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64))) + // Minimum execution time: 25_751 nanoseconds. + Weight::from_ref_time(31_624_681) + // Standard Error: 6_537 + .saturating_add(Weight::from_ref_time(2_990_370).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - // Minimum execution time: 4_775 nanoseconds. - Weight::from_ref_time(5_033_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_296 nanoseconds. + Weight::from_ref_time(5_492_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) /// The range of component `r` is `[0, 99]`. fn unlock_remove(r: u32, ) -> Weight { - // Minimum execution time: 23_245 nanoseconds. - Weight::from_ref_time(30_061_940 as u64) - // Standard Error: 1_523 - .saturating_add(Weight::from_ref_time(34_810 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 25_452 nanoseconds. + Weight::from_ref_time(32_353_825) + // Standard Error: 1_521 + .saturating_add(Weight::from_ref_time(34_816).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) /// The range of component `r` is `[0, 99]`. fn unlock_set(r: u32, ) -> Weight { - // Minimum execution time: 28_063 nanoseconds. - Weight::from_ref_time(30_002_043 as u64) - // Standard Error: 636 - .saturating_add(Weight::from_ref_time(67_182 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 31_115 nanoseconds. + Weight::from_ref_time(32_198_924) + // Standard Error: 557 + .saturating_add(Weight::from_ref_time(70_842).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) /// The range of component `r` is `[1, 100]`. fn remove_vote(r: u32, ) -> Weight { - // Minimum execution time: 15_306 nanoseconds. - Weight::from_ref_time(17_690_130 as u64) - // Standard Error: 836 - .saturating_add(Weight::from_ref_time(68_122 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 16_292 nanoseconds. + Weight::from_ref_time(18_794_631) + // Standard Error: 899 + .saturating_add(Weight::from_ref_time(76_463).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) /// The range of component `r` is `[1, 100]`. fn remove_other_vote(r: u32, ) -> Weight { - // Minimum execution time: 15_392 nanoseconds. - Weight::from_ref_time(17_610_812 as u64) - // Standard Error: 819 - .saturating_add(Weight::from_ref_time(69_086 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 16_173 nanoseconds. + Weight::from_ref_time(18_822_303) + // Standard Error: 943 + .saturating_add(Weight::from_ref_time(75_909).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/polkadot/src/weights/pallet_election_provider_multi_phase.rs b/runtime/polkadot/src/weights/pallet_election_provider_multi_phase.rs index 9d2afa4d2755..885309efc063 100644 --- a/runtime/polkadot/src/weights/pallet_election_provider_multi_phase.rs +++ b/runtime/polkadot/src/weights/pallet_election_provider_multi_phase.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_election_provider_multi_phase` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -53,40 +53,40 @@ impl pallet_election_provider_multi_phase::WeightInfo f // Storage: Staking ForceEra (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) fn on_initialize_nothing() -> Weight { - // Minimum execution time: 15_173 nanoseconds. - Weight::from_ref_time(15_566_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) + // Minimum execution time: 16_694 nanoseconds. + Weight::from_ref_time(17_237_000) + .saturating_add(T::DbWeight::get().reads(8)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_signed() -> Weight { - // Minimum execution time: 13_691 nanoseconds. - Weight::from_ref_time(14_176_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_381 nanoseconds. + Weight::from_ref_time(15_825_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_unsigned() -> Weight { - // Minimum execution time: 13_539 nanoseconds. - Weight::from_ref_time(14_023_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_126 nanoseconds. + Weight::from_ref_time(15_398_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) // Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) fn finalize_signed_phase_accept_solution() -> Weight { - // Minimum execution time: 27_536 nanoseconds. - Weight::from_ref_time(28_008_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 30_260 nanoseconds. + Weight::from_ref_time(30_782_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: System Account (r:1 w:1) fn finalize_signed_phase_reject_solution() -> Weight { - // Minimum execution time: 21_053 nanoseconds. - Weight::from_ref_time(21_495_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 23_469 nanoseconds. + Weight::from_ref_time(23_820_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ElectionProviderMultiPhase SnapshotMetadata (r:0 w:1) // Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) @@ -94,11 +94,11 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// 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 { - // Minimum execution time: 422_358 nanoseconds. - Weight::from_ref_time(435_895_000 as u64) - // Standard Error: 2_376 - .saturating_add(Weight::from_ref_time(268_064 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 443_964 nanoseconds. + Weight::from_ref_time(449_824_000) + // Standard Error: 2_433 + .saturating_add(Weight::from_ref_time(265_620).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) @@ -113,14 +113,14 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn elect_queued(a: u32, d: u32, ) -> Weight { - // Minimum execution time: 282_891 nanoseconds. - Weight::from_ref_time(64_783_615 as u64) - // Standard Error: 6_219 - .saturating_add(Weight::from_ref_time(362_403 as u64).saturating_mul(a as u64)) - // Standard Error: 9_322 - .saturating_add(Weight::from_ref_time(129_048 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 282_209 nanoseconds. + Weight::from_ref_time(71_228_270) + // Standard Error: 6_321 + .saturating_add(Weight::from_ref_time(392_244).saturating_mul(a.into())) + // Standard Error: 9_475 + .saturating_add(Weight::from_ref_time(80_543).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(9)) } // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) @@ -129,10 +129,10 @@ impl pallet_election_provider_multi_phase::WeightInfo f // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) fn submit() -> Weight { - // Minimum execution time: 48_593 nanoseconds. - Weight::from_ref_time(49_233_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 51_153 nanoseconds. + Weight::from_ref_time(51_487_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: ElectionProviderMultiPhase Round (r:1 w:0) @@ -146,14 +146,14 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn submit_unsigned(v: u32, _t: u32, a: u32, _d: u32, ) -> Weight { - // Minimum execution time: 4_793_536 nanoseconds. - Weight::from_ref_time(4_829_131_000 as u64) - // Standard Error: 14_655 - .saturating_add(Weight::from_ref_time(98_228 as u64).saturating_mul(v as u64)) - // Standard Error: 43_429 - .saturating_add(Weight::from_ref_time(4_641_460 as u64).saturating_mul(a as u64)) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_769_127 nanoseconds. + Weight::from_ref_time(4_783_174_000) + // Standard Error: 14_696 + .saturating_add(Weight::from_ref_time(97_722).saturating_mul(v.into())) + // Standard Error: 43_551 + .saturating_add(Weight::from_ref_time(4_438_823).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) @@ -164,12 +164,12 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn feasibility_check(v: u32, _t: u32, a: u32, _d: u32, ) -> Weight { - // Minimum execution time: 3_977_796 nanoseconds. - Weight::from_ref_time(3_993_895_000 as u64) - // Standard Error: 12_592 - .saturating_add(Weight::from_ref_time(207_036 as u64).saturating_mul(v as u64)) - // Standard Error: 37_315 - .saturating_add(Weight::from_ref_time(3_356_343 as u64).saturating_mul(a as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) + // Minimum execution time: 3_948_376 nanoseconds. + Weight::from_ref_time(4_006_077_000) + // Standard Error: 13_237 + .saturating_add(Weight::from_ref_time(216_796).saturating_mul(v.into())) + // Standard Error: 39_228 + .saturating_add(Weight::from_ref_time(3_191_792).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(4)) } } diff --git a/runtime/polkadot/src/weights/pallet_elections_phragmen.rs b/runtime/polkadot/src/weights/pallet_elections_phragmen.rs index 99eb364f1f98..e3dd0773bab4 100644 --- a/runtime/polkadot/src/weights/pallet_elections_phragmen.rs +++ b/runtime/polkadot/src/weights/pallet_elections_phragmen.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_elections_phragmen` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -51,12 +51,12 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Balances Locks (r:1 w:1) /// The range of component `v` is `[1, 16]`. fn vote_equal(v: u32, ) -> Weight { - // Minimum execution time: 30_071 nanoseconds. - Weight::from_ref_time(31_578_033 as u64) - // Standard Error: 3_999 - .saturating_add(Weight::from_ref_time(189_446 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 32_024 nanoseconds. + Weight::from_ref_time(33_854_765) + // Standard Error: 5_505 + .saturating_add(Weight::from_ref_time(140_083).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Candidates (r:1 w:0) // Storage: PhragmenElection Members (r:1 w:0) @@ -65,12 +65,12 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Balances Locks (r:1 w:1) /// The range of component `v` is `[2, 16]`. fn vote_more(v: u32, ) -> Weight { - // Minimum execution time: 40_205 nanoseconds. - Weight::from_ref_time(41_743_927 as u64) - // Standard Error: 5_811 - .saturating_add(Weight::from_ref_time(147_480 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 42_295 nanoseconds. + Weight::from_ref_time(43_940_673) + // Standard Error: 5_953 + .saturating_add(Weight::from_ref_time(124_400).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Candidates (r:1 w:0) // Storage: PhragmenElection Members (r:1 w:0) @@ -79,42 +79,42 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Balances Locks (r:1 w:1) /// The range of component `v` is `[2, 16]`. fn vote_less(v: u32, ) -> Weight { - // Minimum execution time: 39_612 nanoseconds. - Weight::from_ref_time(41_027_731 as u64) - // Standard Error: 5_632 - .saturating_add(Weight::from_ref_time(201_456 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 42_918 nanoseconds. + Weight::from_ref_time(43_662_086) + // Standard Error: 4_747 + .saturating_add(Weight::from_ref_time(152_167).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn remove_voter() -> Weight { - // Minimum execution time: 39_544 nanoseconds. - Weight::from_ref_time(42_718_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 41_331 nanoseconds. + Weight::from_ref_time(41_867_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Candidates (r:1 w:1) // Storage: PhragmenElection Members (r:1 w:0) // Storage: PhragmenElection RunnersUp (r:1 w:0) /// The range of component `c` is `[1, 1000]`. fn submit_candidacy(c: u32, ) -> Weight { - // Minimum execution time: 35_706 nanoseconds. - Weight::from_ref_time(27_153_321 as u64) - // Standard Error: 992 - .saturating_add(Weight::from_ref_time(91_044 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 37_059 nanoseconds. + Weight::from_ref_time(28_850_455) + // Standard Error: 1_018 + .saturating_add(Weight::from_ref_time(95_719).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: PhragmenElection Candidates (r:1 w:1) /// The range of component `c` is `[1, 1000]`. fn renounce_candidacy_candidate(c: u32, ) -> Weight { - // Minimum execution time: 30_444 nanoseconds. - Weight::from_ref_time(22_835_523 as u64) - // Standard Error: 1_029 - .saturating_add(Weight::from_ref_time(71_777 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 32_348 nanoseconds. + Weight::from_ref_time(24_213_078) + // Standard Error: 1_011 + .saturating_add(Weight::from_ref_time(71_484).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: PhragmenElection Members (r:1 w:1) // Storage: PhragmenElection RunnersUp (r:1 w:1) @@ -122,22 +122,22 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn renounce_candidacy_members() -> Weight { - // Minimum execution time: 43_311 nanoseconds. - Weight::from_ref_time(43_994_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 45_843 nanoseconds. + Weight::from_ref_time(46_822_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: PhragmenElection RunnersUp (r:1 w:1) fn renounce_candidacy_runners_up() -> Weight { - // Minimum execution time: 33_291 nanoseconds. - Weight::from_ref_time(34_436_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 34_751 nanoseconds. + Weight::from_ref_time(35_934_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Benchmark Override (r:0 w:0) fn remove_member_without_replacement() -> Weight { // Minimum execution time: 2_000_000_000 nanoseconds. - Weight::from_ref_time(2_000_000_000_000 as u64) + Weight::from_ref_time(2_000_000_000_000) } // Storage: PhragmenElection Members (r:1 w:1) // Storage: System Account (r:1 w:1) @@ -146,10 +146,10 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn remove_member_with_replacement() -> Weight { - // Minimum execution time: 56_677 nanoseconds. - Weight::from_ref_time(58_359_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 60_526 nanoseconds. + Weight::from_ref_time(62_010_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: PhragmenElection Voting (r:5001 w:5000) // Storage: PhragmenElection Members (r:1 w:0) @@ -160,13 +160,13 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn /// The range of component `v` is `[5000, 10000]`. /// The range of component `d` is `[0, 5000]`. fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { - // Minimum execution time: 270_248_956 nanoseconds. - Weight::from_ref_time(271_306_495_000 as u64) - // Standard Error: 233_605 - .saturating_add(Weight::from_ref_time(34_076_228 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(v as u64))) + // Minimum execution time: 285_304_906 nanoseconds. + Weight::from_ref_time(285_891_493_000) + // Standard Error: 248_503 + .saturating_add(Weight::from_ref_time(35_426_073).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) } // Storage: PhragmenElection Candidates (r:1 w:1) // Storage: PhragmenElection Members (r:1 w:1) @@ -181,16 +181,16 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn /// The range of component `v` is `[1, 10000]`. /// The range of component `e` is `[10000, 160000]`. fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { - // Minimum execution time: 27_528_355 nanoseconds. - Weight::from_ref_time(27_615_108_000 as u64) - // Standard Error: 467_319 - .saturating_add(Weight::from_ref_time(41_041_560 as u64).saturating_mul(v as u64)) - // Standard Error: 29_989 - .saturating_add(Weight::from_ref_time(2_059_675 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(269 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().writes(6 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + // Minimum execution time: 29_105_971 nanoseconds. + Weight::from_ref_time(29_380_349_000) + // Standard Error: 463_867 + .saturating_add(Weight::from_ref_time(40_872_900).saturating_mul(v.into())) + // Standard Error: 29_768 + .saturating_add(Weight::from_ref_time(2_025_413).saturating_mul(e.into())) + .saturating_add(T::DbWeight::get().reads(269)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) } } diff --git a/runtime/polkadot/src/weights/pallet_fast_unstake.rs b/runtime/polkadot/src/weights/pallet_fast_unstake.rs index 3ba0765d4a87..f89008944e96 100644 --- a/runtime/polkadot/src/weights/pallet_fast_unstake.rs +++ b/runtime/polkadot/src/weights/pallet_fast_unstake.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_fast_unstake` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -49,56 +49,56 @@ impl pallet_fast_unstake::WeightInfo for WeightInfo // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking SlashingSpans (r:1 w:0) - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Ledger (r:0 w:1) - // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SlashingSpans (r:64 w:0) + // Storage: Staking Bonded (r:64 w:64) + // Storage: Staking Validators (r:64 w:0) + // Storage: Staking Nominators (r:64 w:0) + // Storage: System Account (r:64 w:64) + // Storage: Balances Locks (r:64 w:64) + // Storage: Staking Ledger (r:0 w:64) + // Storage: Staking Payee (r:0 w:64) fn on_idle_unstake() -> Weight { - // Minimum execution time: 71_042 nanoseconds. - Weight::from_ref_time(71_868_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 2_251_333 nanoseconds. + Weight::from_ref_time(2_317_242_000) + .saturating_add(T::DbWeight::get().reads(389)) + .saturating_add(T::DbWeight::get().writes(321)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking ValidatorCount (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) - // Storage: FastUnstake Queue (r:2 w:1) + // Storage: FastUnstake Queue (r:65 w:64) // Storage: FastUnstake CounterForQueue (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking ErasStakers (r:56 w:0) /// The range of component `x` is `[28, 3584]`. fn on_idle_check(x: u32, ) -> Weight { - // Minimum execution time: 508_029 nanoseconds. - Weight::from_ref_time(509_743_000 as u64) - // Standard Error: 12_195 - .saturating_add(Weight::from_ref_time(14_175_618 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(22 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 28_201_563 nanoseconds. + Weight::from_ref_time(28_421_841_000) + // Standard Error: 608_431 + .saturating_add(Weight::from_ref_time(842_395_651).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(85)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(66)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: FastUnstake Queue (r:1 w:1) // Storage: FastUnstake Head (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:2 w:2) - // Storage: VoterList ListBags (r:1 w:1) + // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn register_fast_unstake() -> Weight { - // Minimum execution time: 95_147 nanoseconds. - Weight::from_ref_time(96_423_000 as u64) - .saturating_add(T::DbWeight::get().reads(14 as u64)) - .saturating_add(T::DbWeight::get().writes(10 as u64)) + // Minimum execution time: 129_440 nanoseconds. + Weight::from_ref_time(131_391_000) + .saturating_add(T::DbWeight::get().reads(15)) + .saturating_add(T::DbWeight::get().writes(10)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) @@ -106,15 +106,15 @@ impl pallet_fast_unstake::WeightInfo for WeightInfo // Storage: FastUnstake Head (r:1 w:0) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn deregister() -> Weight { - // Minimum execution time: 40_560 nanoseconds. - Weight::from_ref_time(41_100_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 51_373 nanoseconds. + Weight::from_ref_time(52_351_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FastUnstake ErasToCheckPerBlock (r:0 w:1) fn control() -> Weight { - // Minimum execution time: 3_685 nanoseconds. - Weight::from_ref_time(3_903_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_138 nanoseconds. + Weight::from_ref_time(4_245_000) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/pallet_identity.rs b/runtime/polkadot/src/weights/pallet_identity.rs index 16a08ff316ac..6c48341a6b91 100644 --- a/runtime/polkadot/src/weights/pallet_identity.rs +++ b/runtime/polkadot/src/weights/pallet_identity.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_identity` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -47,52 +47,52 @@ impl pallet_identity::WeightInfo for WeightInfo { // Storage: Identity Registrars (r:1 w:1) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { - // Minimum execution time: 15_843 nanoseconds. - Weight::from_ref_time(18_367_858 as u64) - // Standard Error: 6_600 - .saturating_add(Weight::from_ref_time(96_189 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 17_230 nanoseconds. + Weight::from_ref_time(18_831_768) + // Standard Error: 3_060 + .saturating_add(Weight::from_ref_time(158_012).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) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn set_identity(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 33_756 nanoseconds. - Weight::from_ref_time(33_692_837 as u64) - // Standard Error: 3_623 - .saturating_add(Weight::from_ref_time(80_533 as u64).saturating_mul(r as u64)) - // Standard Error: 707 - .saturating_add(Weight::from_ref_time(299_420 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 36_890 nanoseconds. + Weight::from_ref_time(36_334_451) + // Standard Error: 4_153 + .saturating_add(Weight::from_ref_time(83_699).saturating_mul(r.into())) + // Standard Error: 810 + .saturating_add(Weight::from_ref_time(357_545).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:2 w:2) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { - // Minimum execution time: 9_638 nanoseconds. - Weight::from_ref_time(26_873_592 as u64) - // Standard Error: 4_582 - .saturating_add(Weight::from_ref_time(2_089_827 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 10_500 nanoseconds. + Weight::from_ref_time(28_652_188) + // Standard Error: 4_756 + .saturating_add(Weight::from_ref_time(2_254_536).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()))) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:2) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { - // Minimum execution time: 9_876 nanoseconds. - Weight::from_ref_time(27_132_981 as u64) - // Standard Error: 4_104 - .saturating_add(Weight::from_ref_time(907_310 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 10_684 nanoseconds. + Weight::from_ref_time(29_135_170) + // Standard Error: 4_325 + .saturating_add(Weight::from_ref_time(971_628).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) // Storage: Identity IdentityOf (r:1 w:1) @@ -101,88 +101,88 @@ impl pallet_identity::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. /// The range of component `x` is `[0, 100]`. fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - // Minimum execution time: 48_877 nanoseconds. - Weight::from_ref_time(34_036_193 as u64) - // Standard Error: 4_926 - .saturating_add(Weight::from_ref_time(129_984 as u64).saturating_mul(r as u64)) - // Standard Error: 962 - .saturating_add(Weight::from_ref_time(878_298 as u64).saturating_mul(s as u64)) - // Standard Error: 962 - .saturating_add(Weight::from_ref_time(161_294 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 53_646 nanoseconds. + Weight::from_ref_time(35_490_280) + // Standard Error: 11_049 + .saturating_add(Weight::from_ref_time(172_227).saturating_mul(r.into())) + // Standard Error: 2_157 + .saturating_add(Weight::from_ref_time(951_835).saturating_mul(s.into())) + // Standard Error: 2_157 + .saturating_add(Weight::from_ref_time(179_431).saturating_mul(x.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) // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn request_judgement(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 36_360 nanoseconds. - Weight::from_ref_time(35_038_187 as u64) - // Standard Error: 4_080 - .saturating_add(Weight::from_ref_time(121_407 as u64).saturating_mul(r as u64)) - // Standard Error: 796 - .saturating_add(Weight::from_ref_time(317_545 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 38_625 nanoseconds. + Weight::from_ref_time(36_724_341) + // Standard Error: 5_302 + .saturating_add(Weight::from_ref_time(148_687).saturating_mul(r.into())) + // Standard Error: 1_034 + .saturating_add(Weight::from_ref_time(386_218).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn cancel_request(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 33_392 nanoseconds. - Weight::from_ref_time(31_829_430 as u64) - // Standard Error: 5_041 - .saturating_add(Weight::from_ref_time(100_136 as u64).saturating_mul(r as u64)) - // Standard Error: 983 - .saturating_add(Weight::from_ref_time(316_813 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 35_653 nanoseconds. + Weight::from_ref_time(33_533_408) + // Standard Error: 3_998 + .saturating_add(Weight::from_ref_time(123_268).saturating_mul(r.into())) + // Standard Error: 780 + .saturating_add(Weight::from_ref_time(375_639).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity Registrars (r:1 w:1) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { - // Minimum execution time: 8_200 nanoseconds. - Weight::from_ref_time(9_149_038 as u64) - // Standard Error: 2_439 - .saturating_add(Weight::from_ref_time(122_207 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_966 nanoseconds. + Weight::from_ref_time(9_880_313) + // Standard Error: 2_446 + .saturating_add(Weight::from_ref_time(137_813).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) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { - // Minimum execution time: 8_237 nanoseconds. - Weight::from_ref_time(9_267_742 as u64) - // Standard Error: 2_410 - .saturating_add(Weight::from_ref_time(122_610 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_282 nanoseconds. + Weight::from_ref_time(10_192_241) + // Standard Error: 2_215 + .saturating_add(Weight::from_ref_time(131_233).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) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { - // Minimum execution time: 8_120 nanoseconds. - Weight::from_ref_time(9_089_436 as u64) - // Standard Error: 2_330 - .saturating_add(Weight::from_ref_time(121_665 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_070 nanoseconds. + Weight::from_ref_time(10_027_272) + // Standard Error: 2_433 + .saturating_add(Weight::from_ref_time(125_053).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) // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 19]`. /// The range of component `x` is `[0, 100]`. fn provide_judgement(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 27_286 nanoseconds. - Weight::from_ref_time(26_160_470 as u64) - // Standard Error: 4_870 - .saturating_add(Weight::from_ref_time(110_855 as u64).saturating_mul(r as u64)) - // Standard Error: 901 - .saturating_add(Weight::from_ref_time(533_939 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_147 nanoseconds. + Weight::from_ref_time(28_340_347) + // Standard Error: 4_876 + .saturating_add(Weight::from_ref_time(100_619).saturating_mul(r.into())) + // Standard Error: 902 + .saturating_add(Weight::from_ref_time(636_099).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity IdentityOf (r:1 w:1) @@ -192,62 +192,62 @@ impl pallet_identity::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. /// The range of component `x` is `[0, 100]`. fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight { - // Minimum execution time: 60_659 nanoseconds. - Weight::from_ref_time(46_125_203 as u64) - // Standard Error: 10_008 - .saturating_add(Weight::from_ref_time(120_794 as u64).saturating_mul(r as u64)) - // Standard Error: 1_954 - .saturating_add(Weight::from_ref_time(886_225 as u64).saturating_mul(s as u64)) - // Standard Error: 1_954 - .saturating_add(Weight::from_ref_time(151_157 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 66_106 nanoseconds. + Weight::from_ref_time(48_177_759) + // Standard Error: 4_574 + .saturating_add(Weight::from_ref_time(140_713).saturating_mul(r.into())) + // Standard Error: 893 + .saturating_add(Weight::from_ref_time(947_959).saturating_mul(s.into())) + // Standard Error: 893 + .saturating_add(Weight::from_ref_time(179_678).saturating_mul(x.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) // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { - // Minimum execution time: 30_363 nanoseconds. - Weight::from_ref_time(36_833_789 as u64) - // Standard Error: 2_192 - .saturating_add(Weight::from_ref_time(70_760 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 32_596 nanoseconds. + Weight::from_ref_time(38_644_808) + // Standard Error: 1_736 + .saturating_add(Weight::from_ref_time(80_372).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) // Storage: Identity SuperOf (r:1 w:1) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { - // Minimum execution time: 12_991 nanoseconds. - Weight::from_ref_time(15_363_557 as u64) - // Standard Error: 690 - .saturating_add(Weight::from_ref_time(27_000 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 14_796 nanoseconds. + Weight::from_ref_time(16_788_043) + // Standard Error: 624 + .saturating_add(Weight::from_ref_time(28_891).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) // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { - // Minimum execution time: 34_425 nanoseconds. - Weight::from_ref_time(37_755_916 as u64) - // Standard Error: 1_179 - .saturating_add(Weight::from_ref_time(62_401 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 37_696 nanoseconds. + Weight::from_ref_time(40_868_069) + // Standard Error: 1_210 + .saturating_add(Weight::from_ref_time(62_113).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) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { - // Minimum execution time: 23_829 nanoseconds. - Weight::from_ref_time(27_592_997 as u64) - // Standard Error: 1_188 - .saturating_add(Weight::from_ref_time(64_211 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 25_674 nanoseconds. + Weight::from_ref_time(29_744_176) + // Standard Error: 1_203 + .saturating_add(Weight::from_ref_time(67_072).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/polkadot/src/weights/pallet_im_online.rs b/runtime/polkadot/src/weights/pallet_im_online.rs index 24a74d371bf1..1d4fbaa4c0c3 100644 --- a/runtime/polkadot/src/weights/pallet_im_online.rs +++ b/runtime/polkadot/src/weights/pallet_im_online.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_im_online` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -52,13 +52,13 @@ impl pallet_im_online::WeightInfo for WeightInfo { /// The range of component `k` is `[1, 1000]`. /// The range of component `e` is `[1, 100]`. fn validate_unsigned_and_then_heartbeat(k: u32, e: u32, ) -> Weight { - // Minimum execution time: 96_686 nanoseconds. - Weight::from_ref_time(76_489_797 as u64) - // Standard Error: 194 - .saturating_add(Weight::from_ref_time(23_059 as u64).saturating_mul(k as u64)) - // Standard Error: 1_956 - .saturating_add(Weight::from_ref_time(297_116 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 96_694 nanoseconds. + Weight::from_ref_time(78_587_764) + // Standard Error: 304 + .saturating_add(Weight::from_ref_time(23_623).saturating_mul(k.into())) + // Standard Error: 3_072 + .saturating_add(Weight::from_ref_time(331_036).saturating_mul(e.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/pallet_indices.rs b/runtime/polkadot/src/weights/pallet_indices.rs index 5ec530cb457e..05b4d6441313 100644 --- a/runtime/polkadot/src/weights/pallet_indices.rs +++ b/runtime/polkadot/src/weights/pallet_indices.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_indices` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -46,39 +46,39 @@ pub struct WeightInfo(PhantomData); impl pallet_indices::WeightInfo for WeightInfo { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - // Minimum execution time: 25_307 nanoseconds. - Weight::from_ref_time(25_822_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 27_438 nanoseconds. + Weight::from_ref_time(27_968_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - // Minimum execution time: 31_113 nanoseconds. - Weight::from_ref_time(32_000_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 33_878 nanoseconds. + Weight::from_ref_time(34_231_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - // Minimum execution time: 25_974 nanoseconds. - Weight::from_ref_time(26_285_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 28_102 nanoseconds. + Weight::from_ref_time(28_607_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - // Minimum execution time: 26_185 nanoseconds. - Weight::from_ref_time(26_636_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 28_602 nanoseconds. + Weight::from_ref_time(28_983_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - // Minimum execution time: 31_130 nanoseconds. - Weight::from_ref_time(31_800_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 33_679 nanoseconds. + Weight::from_ref_time(34_218_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/pallet_membership.rs b/runtime/polkadot/src/weights/pallet_membership.rs index bf4c5cd4a445..c4556454ffbe 100644 --- a/runtime/polkadot/src/weights/pallet_membership.rs +++ b/runtime/polkadot/src/weights/pallet_membership.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_membership` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -50,12 +50,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 99]`. fn add_member(m: u32, ) -> Weight { - // Minimum execution time: 19_229 nanoseconds. - Weight::from_ref_time(20_166_733 as u64) - // Standard Error: 1_078 - .saturating_add(Weight::from_ref_time(36_764 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 21_960 nanoseconds. + Weight::from_ref_time(22_853_152) + // Standard Error: 546 + .saturating_add(Weight::from_ref_time(41_435).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -64,12 +64,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[2, 100]`. fn remove_member(m: u32, ) -> Weight { - // Minimum execution time: 21_778 nanoseconds. - Weight::from_ref_time(22_484_271 as u64) - // Standard Error: 499 - .saturating_add(Weight::from_ref_time(34_154 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 23_713 nanoseconds. + Weight::from_ref_time(25_201_268) + // Standard Error: 521 + .saturating_add(Weight::from_ref_time(36_459).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -78,12 +78,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[2, 100]`. fn swap_member(m: u32, ) -> Weight { - // Minimum execution time: 21_853 nanoseconds. - Weight::from_ref_time(22_718_867 as u64) - // Standard Error: 623 - .saturating_add(Weight::from_ref_time(43_677 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 24_740 nanoseconds. + Weight::from_ref_time(25_232_209) + // Standard Error: 508 + .saturating_add(Weight::from_ref_time(51_435).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -92,12 +92,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn reset_member(m: u32, ) -> Weight { - // Minimum execution time: 20_805 nanoseconds. - Weight::from_ref_time(22_284_415 as u64) - // Standard Error: 764 - .saturating_add(Weight::from_ref_time(157_189 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 23_896 nanoseconds. + Weight::from_ref_time(25_910_024) + // Standard Error: 2_537 + .saturating_add(Weight::from_ref_time(157_048).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -106,33 +106,33 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn change_key(m: u32, ) -> Weight { - // Minimum execution time: 22_056 nanoseconds. - Weight::from_ref_time(23_040_470 as u64) - // Standard Error: 601 - .saturating_add(Weight::from_ref_time(44_062 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 24_513 nanoseconds. + Weight::from_ref_time(25_845_559) + // Standard Error: 696 + .saturating_add(Weight::from_ref_time(50_292).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: TechnicalMembership Members (r:1 w:0) // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn set_prime(m: u32, ) -> Weight { - // Minimum execution time: 7_968 nanoseconds. - Weight::from_ref_time(8_412_859 as u64) - // Standard Error: 213 - .saturating_add(Weight::from_ref_time(9_618 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 8_975 nanoseconds. + Weight::from_ref_time(9_329_864) + // Standard Error: 198 + .saturating_add(Weight::from_ref_time(9_927).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn clear_prime(m: u32, ) -> Weight { - // Minimum execution time: 4_511 nanoseconds. - Weight::from_ref_time(4_850_929 as u64) - // Standard Error: 183 - .saturating_add(Weight::from_ref_time(356 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 5_083 nanoseconds. + Weight::from_ref_time(5_442_895) + // Standard Error: 142 + .saturating_add(Weight::from_ref_time(1_435).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/polkadot/src/weights/pallet_multisig.rs b/runtime/polkadot/src/weights/pallet_multisig.rs index cd8a795eeaa3..b9305b0a4c58 100644 --- a/runtime/polkadot/src/weights/pallet_multisig.rs +++ b/runtime/polkadot/src/weights/pallet_multisig.rs @@ -16,8 +16,8 @@ //! Autogenerated weights for `pallet_multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-26, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bm2`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 // Executed Command: @@ -28,11 +28,11 @@ // --steps=50 // --repeat=20 // --pallet=pallet_multisig -// --extrinsic= +// --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --header=./file_header.txt -// --output=runtime/polkadot/src/weights/ +// --output=./runtime/polkadot/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -46,81 +46,81 @@ pub struct WeightInfo(PhantomData); impl pallet_multisig::WeightInfo for WeightInfo { /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { - // Minimum execution time: 14_333 nanoseconds. - Weight::from_ref_time(14_680_513 as u64) + // Minimum execution time: 15_141 nanoseconds. + Weight::from_ref_time(15_659_829) // Standard Error: 3 - .saturating_add(Weight::from_ref_time(478 as u64).saturating_mul(z as u64)) + .saturating_add(Weight::from_ref_time(602).saturating_mul(z.into())) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) /// 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 { - // Minimum execution time: 41_940 nanoseconds. - Weight::from_ref_time(34_164_952 as u64) - // Standard Error: 758 - .saturating_add(Weight::from_ref_time(84_361 as u64).saturating_mul(s as u64)) - // Standard Error: 7 - .saturating_add(Weight::from_ref_time(1_515 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 44_874 nanoseconds. + Weight::from_ref_time(37_757_867) + // Standard Error: 1_278 + .saturating_add(Weight::from_ref_time(80_504).saturating_mul(s.into())) + // Standard Error: 12 + .saturating_add(Weight::from_ref_time(1_609).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Multisig Multisigs (r:1 w:1) /// 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 { - // Minimum execution time: 32_061 nanoseconds. - Weight::from_ref_time(25_242_175 as u64) - // Standard Error: 488 - .saturating_add(Weight::from_ref_time(74_544 as u64).saturating_mul(s as u64)) - // Standard Error: 4 - .saturating_add(Weight::from_ref_time(1_451 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 34_339 nanoseconds. + Weight::from_ref_time(27_565_615) + // Standard Error: 600 + .saturating_add(Weight::from_ref_time(78_419).saturating_mul(s.into())) + // Standard Error: 5 + .saturating_add(Weight::from_ref_time(1_586).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) // Storage: System Account (r:1 w:1) /// 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 { - // Minimum execution time: 45_799 nanoseconds. - Weight::from_ref_time(36_673_371 as u64) - // Standard Error: 602 - .saturating_add(Weight::from_ref_time(105_602 as u64).saturating_mul(s as u64)) - // Standard Error: 5 - .saturating_add(Weight::from_ref_time(1_489 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 49_252 nanoseconds. + Weight::from_ref_time(39_821_299) + // Standard Error: 964 + .saturating_add(Weight::from_ref_time(108_976).saturating_mul(s.into())) + // Standard Error: 9 + .saturating_add(Weight::from_ref_time(1_637).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) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { - // Minimum execution time: 30_746 nanoseconds. - Weight::from_ref_time(33_495_066 as u64) - // Standard Error: 1_027 - .saturating_add(Weight::from_ref_time(85_901 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 33_110 nanoseconds. + Weight::from_ref_time(35_715_434) + // Standard Error: 963 + .saturating_add(Weight::from_ref_time(90_748).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Multisig Multisigs (r:1 w:1) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { - // Minimum execution time: 21_939 nanoseconds. - Weight::from_ref_time(23_359_812 as u64) - // Standard Error: 626 - .saturating_add(Weight::from_ref_time(86_183 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 24_600 nanoseconds. + Weight::from_ref_time(25_608_310) + // Standard Error: 601 + .saturating_add(Weight::from_ref_time(84_721).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) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { - // Minimum execution time: 32_246 nanoseconds. - Weight::from_ref_time(33_400_827 as u64) - // Standard Error: 746 - .saturating_add(Weight::from_ref_time(85_743 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 34_071 nanoseconds. + Weight::from_ref_time(36_806_655) + // Standard Error: 1_417 + .saturating_add(Weight::from_ref_time(81_468).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/pallet_nomination_pools.rs b/runtime/polkadot/src/weights/pallet_nomination_pools.rs index 4dedf1a4375c..83822fe96acf 100644 --- a/runtime/polkadot/src/weights/pallet_nomination_pools.rs +++ b/runtime/polkadot/src/weights/pallet_nomination_pools.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_nomination_pools` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -47,65 +47,66 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools MinJoinBond (r:1 w:0) // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:2 w:1) // Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) // Storage: NominationPools MaxPoolMembers (r:1 w:0) // Storage: NominationPools CounterForPoolMembers (r:1 w:1) - // Storage: Staking Bonded (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn join() -> Weight { - // Minimum execution time: 137_659 nanoseconds. - Weight::from_ref_time(141_867_000 as u64) - .saturating_add(T::DbWeight::get().reads(17 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) + // Minimum execution time: 143_103 nanoseconds. + Weight::from_ref_time(146_231_000) + .saturating_add(T::DbWeight::get().reads(17)) + .saturating_add(T::DbWeight::get().writes(12)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:3 w:2) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra_transfer() -> Weight { - // Minimum execution time: 135_584 nanoseconds. - Weight::from_ref_time(138_267_000 as u64) - .saturating_add(T::DbWeight::get().reads(14 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) + // Minimum execution time: 140_240 nanoseconds. + Weight::from_ref_time(141_483_000) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(12)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:3 w:3) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:2 w:2) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra_reward() -> Weight { - // Minimum execution time: 139_022 nanoseconds. - Weight::from_ref_time(141_990_000 as u64) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) + // Minimum execution time: 144_939 nanoseconds. + Weight::from_ref_time(146_128_000) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(12)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:1 w:1) fn claim_payout() -> Weight { - // Minimum execution time: 55_953 nanoseconds. - Weight::from_ref_time(56_404_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 54_769 nanoseconds. + Weight::from_ref_time(55_454_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: System Account (r:2 w:1) // Storage: Staking CurrentEra (r:1 w:0) @@ -113,52 +114,53 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: Staking MinNominatorBond (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:3 w:3) - // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListBags (r:2 w:2) // Storage: NominationPools SubPoolsStorage (r:1 w:1) // Storage: NominationPools CounterForSubPoolsStorage (r:1 w:1) fn unbond() -> Weight { - // Minimum execution time: 137_634 nanoseconds. - Weight::from_ref_time(138_697_000 as u64) - .saturating_add(T::DbWeight::get().reads(18 as u64)) - .saturating_add(T::DbWeight::get().writes(13 as u64)) + // Minimum execution time: 145_690 nanoseconds. + Weight::from_ref_time(146_966_000) + .saturating_add(T::DbWeight::get().reads(18)) + .saturating_add(T::DbWeight::get().writes(13)) } // Storage: NominationPools BondedPools (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Balances Locks (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { - // Minimum execution time: 50_029 nanoseconds. - Weight::from_ref_time(51_873_509 as u64) - // Standard Error: 1_109 - .saturating_add(Weight::from_ref_time(8_889 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 57_909 nanoseconds. + Weight::from_ref_time(59_529_561) + // Standard Error: 897 + .saturating_add(Weight::from_ref_time(14_204).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools SubPoolsStorage (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) // Storage: NominationPools CounterForPoolMembers (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 89_911 nanoseconds. - Weight::from_ref_time(92_313_754 as u64) - // Standard Error: 1_344 - .saturating_add(Weight::from_ref_time(21_018 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 98_716 nanoseconds. + Weight::from_ref_time(100_649_362) + // Standard Error: 1_785 + .saturating_add(Weight::from_ref_time(16_983).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools SubPoolsStorage (r:1 w:1) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) // Storage: Staking SlashingSpans (r:1 w:0) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:0) @@ -174,25 +176,27 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools CounterForBondedPools (r:1 w:1) // Storage: Staking Payee (r:0 w:1) /// The range of component `s` is `[0, 100]`. - fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - // Minimum execution time: 142_501 nanoseconds. - Weight::from_ref_time(145_720_383 as u64) - .saturating_add(T::DbWeight::get().reads(20 as u64)) - .saturating_add(T::DbWeight::get().writes(17 as u64)) + fn withdraw_unbonded_kill(s: u32, ) -> Weight { + // Minimum execution time: 148_300 nanoseconds. + Weight::from_ref_time(151_339_484) + // Standard Error: 2_554 + .saturating_add(Weight::from_ref_time(3_671).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(20)) + .saturating_add(T::DbWeight::get().writes(17)) } + // Storage: NominationPools LastPoolId (r:1 w:1) // Storage: Staking MinNominatorBond (r:1 w:0) // Storage: NominationPools MinCreateBond (r:1 w:0) // Storage: NominationPools MinJoinBond (r:1 w:0) // Storage: NominationPools MaxPools (r:1 w:0) // Storage: NominationPools CounterForBondedPools (r:1 w:1) // Storage: NominationPools PoolMembers (r:1 w:1) - // Storage: NominationPools LastPoolId (r:1 w:1) // Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) // Storage: NominationPools MaxPoolMembers (r:1 w:0) // Storage: NominationPools CounterForPoolMembers (r:1 w:1) // Storage: System Account (r:2 w:2) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) @@ -202,52 +206,53 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools BondedPools (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn create() -> Weight { - // Minimum execution time: 129_279 nanoseconds. - Weight::from_ref_time(130_518_000 as u64) - .saturating_add(T::DbWeight::get().reads(21 as u64)) - .saturating_add(T::DbWeight::get().writes(15 as u64)) + // Minimum execution time: 131_110 nanoseconds. + Weight::from_ref_time(134_810_000) + .saturating_add(T::DbWeight::get().reads(21)) + .saturating_add(T::DbWeight::get().writes(15)) } // Storage: NominationPools BondedPools (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinNominatorBond (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) // Storage: Staking MaxNominatorsCount (r:1 w:0) // Storage: Staking Validators (r:2 w:0) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListNodes (r:1 w:1) // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 60_954 nanoseconds. - Weight::from_ref_time(61_463_684 as u64) - // Standard Error: 4_901 - .saturating_add(Weight::from_ref_time(1_149_069 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 64_081 nanoseconds. + Weight::from_ref_time(65_357_718) + // Standard Error: 7_191 + .saturating_add(Weight::from_ref_time(1_010_507).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: NominationPools BondedPools (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) fn set_state() -> Weight { - // Minimum execution time: 34_554 nanoseconds. - Weight::from_ref_time(35_453_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 38_828 nanoseconds. + Weight::from_ref_time(39_794_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: NominationPools BondedPools (r:1 w:0) // Storage: NominationPools Metadata (r:1 w:1) // Storage: NominationPools CounterForMetadata (r:1 w:1) /// The range of component `n` is `[1, 256]`. fn set_metadata(n: u32, ) -> Weight { - // Minimum execution time: 16_327 nanoseconds. - Weight::from_ref_time(17_114_673 as u64) - // Standard Error: 135 - .saturating_add(Weight::from_ref_time(176 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 15_439 nanoseconds. + Weight::from_ref_time(16_039_093) + // Standard Error: 122 + .saturating_add(Weight::from_ref_time(1_612).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: NominationPools MinJoinBond (r:0 w:1) // Storage: NominationPools MaxPoolMembers (r:0 w:1) @@ -255,18 +260,19 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools MinCreateBond (r:0 w:1) // Storage: NominationPools MaxPools (r:0 w:1) fn set_configs() -> Weight { - // Minimum execution time: 7_390 nanoseconds. - Weight::from_ref_time(7_595_000 as u64) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 6_258 nanoseconds. + Weight::from_ref_time(6_417_000) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: NominationPools BondedPools (r:1 w:1) fn update_roles() -> Weight { - // Minimum execution time: 25_740 nanoseconds. - Weight::from_ref_time(26_148_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 25_465 nanoseconds. + Weight::from_ref_time(25_862_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: NominationPools BondedPools (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -275,9 +281,9 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Minimum execution time: 59_514 nanoseconds. - Weight::from_ref_time(60_304_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 66_354 nanoseconds. + Weight::from_ref_time(67_067_000) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(5)) } } diff --git a/runtime/polkadot/src/weights/pallet_preimage.rs b/runtime/polkadot/src/weights/pallet_preimage.rs index 2c1d2d36766b..3e00fe90a37c 100644 --- a/runtime/polkadot/src/weights/pallet_preimage.rs +++ b/runtime/polkadot/src/weights/pallet_preimage.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_preimage` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -48,99 +48,99 @@ impl pallet_preimage::WeightInfo for WeightInfo { // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { - // Minimum execution time: 27_619 nanoseconds. - Weight::from_ref_time(27_814_000 as u64) + // Minimum execution time: 30_811 nanoseconds. + Weight::from_ref_time(31_480_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_277 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_369).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { - // Minimum execution time: 19_875 nanoseconds. - Weight::from_ref_time(20_055_000 as u64) + // Minimum execution time: 21_142 nanoseconds. + Weight::from_ref_time(21_458_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_278 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_368).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { - // Minimum execution time: 18_167 nanoseconds. - Weight::from_ref_time(18_540_000 as u64) - // Standard Error: 2 - .saturating_add(Weight::from_ref_time(2_292 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 19_472 nanoseconds. + Weight::from_ref_time(19_721_000) + // Standard Error: 1 + .saturating_add(Weight::from_ref_time(2_369).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_preimage() -> Weight { - // Minimum execution time: 36_691 nanoseconds. - Weight::from_ref_time(38_570_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 41_810 nanoseconds. + Weight::from_ref_time(43_330_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_no_deposit_preimage() -> Weight { - // Minimum execution time: 25_920 nanoseconds. - Weight::from_ref_time(26_891_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 30_394 nanoseconds. + Weight::from_ref_time(31_752_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_preimage() -> Weight { - // Minimum execution time: 25_999 nanoseconds. - Weight::from_ref_time(27_810_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_415 nanoseconds. + Weight::from_ref_time(27_561_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_no_deposit_preimage() -> Weight { - // Minimum execution time: 13_968 nanoseconds. - Weight::from_ref_time(15_524_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 13_855 nanoseconds. + Weight::from_ref_time(14_614_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_unnoted_preimage() -> Weight { - // Minimum execution time: 17_087 nanoseconds. - Weight::from_ref_time(17_859_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 18_789 nanoseconds. + Weight::from_ref_time(19_438_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_requested_preimage() -> Weight { - // Minimum execution time: 7_840 nanoseconds. - Weight::from_ref_time(8_341_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_786 nanoseconds. + Weight::from_ref_time(9_201_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_preimage() -> Weight { - // Minimum execution time: 26_449 nanoseconds. - Weight::from_ref_time(27_824_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 26_958 nanoseconds. + Weight::from_ref_time(27_848_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_unnoted_preimage() -> Weight { - // Minimum execution time: 7_712 nanoseconds. - Weight::from_ref_time(8_055_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_899 nanoseconds. + Weight::from_ref_time(9_226_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_multi_referenced_preimage() -> Weight { - // Minimum execution time: 7_883 nanoseconds. - Weight::from_ref_time(8_212_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_887 nanoseconds. + Weight::from_ref_time(9_215_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/pallet_proxy.rs b/runtime/polkadot/src/weights/pallet_proxy.rs index f843992e5661..f926a7feb06b 100644 --- a/runtime/polkadot/src/weights/pallet_proxy.rs +++ b/runtime/polkadot/src/weights/pallet_proxy.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_proxy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -47,11 +47,11 @@ impl pallet_proxy::WeightInfo for WeightInfo { // Storage: Proxy Proxies (r:1 w:0) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { - // Minimum execution time: 19_011 nanoseconds. - Weight::from_ref_time(20_076_741 as u64) - // Standard Error: 1_518 - .saturating_add(Weight::from_ref_time(55_831 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 21_329 nanoseconds. + Weight::from_ref_time(23_204_129) + // Standard Error: 4_778 + .saturating_add(Weight::from_ref_time(7_081).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) @@ -59,42 +59,42 @@ impl pallet_proxy::WeightInfo for WeightInfo { /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 37_088 nanoseconds. - Weight::from_ref_time(36_581_632 as u64) - // Standard Error: 1_964 - .saturating_add(Weight::from_ref_time(116_190 as u64).saturating_mul(a as u64)) - // Standard Error: 2_030 - .saturating_add(Weight::from_ref_time(41_547 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_046 nanoseconds. + Weight::from_ref_time(39_926_546) + // Standard Error: 1_973 + .saturating_add(Weight::from_ref_time(134_587).saturating_mul(a.into())) + // Standard Error: 2_039 + .saturating_add(Weight::from_ref_time(41_747).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) // Storage: System Account (r:1 w:1) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn remove_announcement(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 25_299 nanoseconds. - Weight::from_ref_time(26_801_993 as u64) - // Standard Error: 2_746 - .saturating_add(Weight::from_ref_time(102_732 as u64).saturating_mul(a as u64)) - // Standard Error: 2_837 - .saturating_add(Weight::from_ref_time(318 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 27_653 nanoseconds. + Weight::from_ref_time(28_516_149) + // Standard Error: 1_454 + .saturating_add(Weight::from_ref_time(135_988).saturating_mul(a.into())) + // Standard Error: 1_502 + .saturating_add(Weight::from_ref_time(5_439).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) // Storage: System Account (r:1 w:1) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn reject_announcement(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 25_178 nanoseconds. - Weight::from_ref_time(26_248_780 as u64) - // Standard Error: 1_710 - .saturating_add(Weight::from_ref_time(116_285 as u64).saturating_mul(a as u64)) - // Standard Error: 1_767 - .saturating_add(Weight::from_ref_time(1_860 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 27_549 nanoseconds. + Weight::from_ref_time(28_723_806) + // Standard Error: 1_606 + .saturating_add(Weight::from_ref_time(128_854).saturating_mul(a.into())) + // Standard Error: 1_659 + .saturating_add(Weight::from_ref_time(3_709).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) // Storage: Proxy Announcements (r:1 w:1) @@ -102,64 +102,64 @@ impl pallet_proxy::WeightInfo for WeightInfo { /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 32_878 nanoseconds. - Weight::from_ref_time(34_386_513 as u64) - // Standard Error: 1_955 - .saturating_add(Weight::from_ref_time(97_872 as u64).saturating_mul(a as u64)) - // Standard Error: 2_020 - .saturating_add(Weight::from_ref_time(25_879 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 35_861 nanoseconds. + Weight::from_ref_time(37_444_836) + // Standard Error: 2_432 + .saturating_add(Weight::from_ref_time(114_339).saturating_mul(a.into())) + // Standard Error: 2_513 + .saturating_add(Weight::from_ref_time(30_891).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) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { - // Minimum execution time: 26_410 nanoseconds. - Weight::from_ref_time(27_653_752 as u64) - // Standard Error: 2_000 - .saturating_add(Weight::from_ref_time(57_860 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_594 nanoseconds. + Weight::from_ref_time(30_718_568) + // Standard Error: 1_883 + .saturating_add(Weight::from_ref_time(76_814).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) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { - // Minimum execution time: 26_506 nanoseconds. - Weight::from_ref_time(27_604_932 as u64) - // Standard Error: 1_863 - .saturating_add(Weight::from_ref_time(78_466 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_044 nanoseconds. + Weight::from_ref_time(30_776_120) + // Standard Error: 2_244 + .saturating_add(Weight::from_ref_time(95_302).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) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { - // Minimum execution time: 22_696 nanoseconds. - Weight::from_ref_time(23_736_641 as u64) - // Standard Error: 1_616 - .saturating_add(Weight::from_ref_time(50_577 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 25_496 nanoseconds. + Weight::from_ref_time(26_827_913) + // Standard Error: 1_766 + .saturating_add(Weight::from_ref_time(48_173).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) // Storage: Proxy Proxies (r:1 w:1) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { - // Minimum execution time: 29_461 nanoseconds. - Weight::from_ref_time(30_835_016 as u64) - // Standard Error: 1_587 - .saturating_add(Weight::from_ref_time(23_834 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 32_980 nanoseconds. + Weight::from_ref_time(34_087_853) + // Standard Error: 2_002 + .saturating_add(Weight::from_ref_time(27_277).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Proxy Proxies (r:1 w:1) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { - // Minimum execution time: 24_319 nanoseconds. - Weight::from_ref_time(25_652_003 as u64) - // Standard Error: 1_697 - .saturating_add(Weight::from_ref_time(28_118 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 27_148 nanoseconds. + Weight::from_ref_time(28_301_699) + // Standard Error: 1_605 + .saturating_add(Weight::from_ref_time(40_708).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/pallet_scheduler.rs b/runtime/polkadot/src/weights/pallet_scheduler.rs index 5206f8b19506..de5d5aea83fb 100644 --- a/runtime/polkadot/src/weights/pallet_scheduler.rs +++ b/runtime/polkadot/src/weights/pallet_scheduler.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_scheduler` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -46,95 +46,95 @@ pub struct WeightInfo(PhantomData); impl pallet_scheduler::WeightInfo for WeightInfo { // Storage: Scheduler IncompleteSince (r:1 w:1) fn service_agendas_base() -> Weight { - // Minimum execution time: 4_236 nanoseconds. - Weight::from_ref_time(4_539_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_882 nanoseconds. + Weight::from_ref_time(4_988_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 50]`. fn service_agenda_base(s: u32, ) -> Weight { - // Minimum execution time: 3_651 nanoseconds. - Weight::from_ref_time(6_843_488 as u64) - // Standard Error: 1_965 - .saturating_add(Weight::from_ref_time(579_324 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_300 nanoseconds. + Weight::from_ref_time(7_468_138) + // Standard Error: 1_864 + .saturating_add(Weight::from_ref_time(673_619).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } fn service_task_base() -> Weight { - // Minimum execution time: 9_244 nanoseconds. - Weight::from_ref_time(9_537_000 as u64) + // Minimum execution time: 9_989 nanoseconds. + Weight::from_ref_time(10_282_000) } // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) /// The range of component `s` is `[128, 4194304]`. fn service_task_fetched(s: u32, ) -> Weight { - // Minimum execution time: 20_377 nanoseconds. - Weight::from_ref_time(20_733_000 as u64) + // Minimum execution time: 22_100 nanoseconds. + Weight::from_ref_time(22_392_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(1_250 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(1_246).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:0 w:1) fn service_task_named() -> Weight { - // Minimum execution time: 10_526 nanoseconds. - Weight::from_ref_time(10_839_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_262 nanoseconds. + Weight::from_ref_time(11_618_000) + .saturating_add(T::DbWeight::get().writes(1)) } fn service_task_periodic() -> Weight { - // Minimum execution time: 9_130 nanoseconds. - Weight::from_ref_time(9_476_000 as u64) + // Minimum execution time: 9_703 nanoseconds. + Weight::from_ref_time(10_061_000) } fn execute_dispatch_signed() -> Weight { - // Minimum execution time: 3_644 nanoseconds. - Weight::from_ref_time(3_761_000 as u64) + // Minimum execution time: 4_326 nanoseconds. + Weight::from_ref_time(4_452_000) } fn execute_dispatch_unsigned() -> Weight { - // Minimum execution time: 3_604 nanoseconds. - Weight::from_ref_time(3_738_000 as u64) + // Minimum execution time: 4_301 nanoseconds. + Weight::from_ref_time(4_414_000) } // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 49]`. fn schedule(s: u32, ) -> Weight { - // Minimum execution time: 16_561 nanoseconds. - Weight::from_ref_time(20_688_245 as u64) - // Standard Error: 2_610 - .saturating_add(Weight::from_ref_time(602_897 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 17_902 nanoseconds. + Weight::from_ref_time(22_354_786) + // Standard Error: 2_469 + .saturating_add(Weight::from_ref_time(692_078).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) // Storage: Scheduler Lookup (r:0 w:1) /// The range of component `s` is `[1, 50]`. fn cancel(s: u32, ) -> Weight { - // Minimum execution time: 18_830 nanoseconds. - Weight::from_ref_time(20_815_969 as u64) - // Standard Error: 2_132 - .saturating_add(Weight::from_ref_time(598_343 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 20_924 nanoseconds. + Weight::from_ref_time(22_194_832) + // Standard Error: 1_827 + .saturating_add(Weight::from_ref_time(688_433).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 49]`. fn schedule_named(s: u32, ) -> Weight { - // Minimum execution time: 18_755 nanoseconds. - Weight::from_ref_time(23_838_238 as u64) - // Standard Error: 3_430 - .saturating_add(Weight::from_ref_time(628_138 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 20_649 nanoseconds. + Weight::from_ref_time(25_859_620) + // Standard Error: 3_439 + .saturating_add(Weight::from_ref_time(716_369).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[1, 50]`. fn cancel_named(s: u32, ) -> Weight { - // Minimum execution time: 19_761 nanoseconds. - Weight::from_ref_time(22_583_852 as u64) - // Standard Error: 2_440 - .saturating_add(Weight::from_ref_time(612_208 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 21_347 nanoseconds. + Weight::from_ref_time(23_894_279) + // Standard Error: 2_268 + .saturating_add(Weight::from_ref_time(709_491).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/polkadot/src/weights/pallet_session.rs b/runtime/polkadot/src/weights/pallet_session.rs index 85494036559b..d779eb021067 100644 --- a/runtime/polkadot/src/weights/pallet_session.rs +++ b/runtime/polkadot/src/weights/pallet_session.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_session` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -48,18 +48,18 @@ impl pallet_session::WeightInfo for WeightInfo { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:6 w:6) fn set_keys() -> Weight { - // Minimum execution time: 48_470 nanoseconds. - Weight::from_ref_time(49_717_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 52_041 nanoseconds. + Weight::from_ref_time(54_043_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:0 w:6) fn purge_keys() -> Weight { - // Minimum execution time: 36_565 nanoseconds. - Weight::from_ref_time(37_601_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 39_425 nanoseconds. + Weight::from_ref_time(41_088_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(7)) } } diff --git a/runtime/polkadot/src/weights/pallet_staking.rs b/runtime/polkadot/src/weights/pallet_staking.rs index 1dcaf61b515e..6520c5551f5b 100644 --- a/runtime/polkadot/src/weights/pallet_staking.rs +++ b/runtime/polkadot/src/weights/pallet_staking.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_staking` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -50,10 +50,10 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - // Minimum execution time: 45_040 nanoseconds. - Weight::from_ref_time(45_590_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 47_622 nanoseconds. + Weight::from_ref_time(48_195_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) @@ -61,10 +61,10 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra() -> Weight { - // Minimum execution time: 81_298 nanoseconds. - Weight::from_ref_time(81_990_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 86_546 nanoseconds. + Weight::from_ref_time(87_502_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Nominators (r:1 w:0) @@ -76,10 +76,10 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListBags (r:2 w:2) fn unbond() -> Weight { - // Minimum execution time: 84_548 nanoseconds. - Weight::from_ref_time(85_146_000 as u64) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 91_301 nanoseconds. + Weight::from_ref_time(91_901_000) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) @@ -87,12 +87,12 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 37_601 nanoseconds. - Weight::from_ref_time(39_116_442 as u64) - // Standard Error: 767 - .saturating_add(Weight::from_ref_time(26_871 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 40_122 nanoseconds. + Weight::from_ref_time(42_062_628) + // Standard Error: 1_675 + .saturating_add(Weight::from_ref_time(29_165).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) @@ -107,12 +107,16 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. - fn withdraw_unbonded_kill(_s: u32, ) -> Weight { - // Minimum execution time: 72_644 nanoseconds. - Weight::from_ref_time(74_496_831 as u64) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(11 as u64)) + fn withdraw_unbonded_kill(s: u32, ) -> Weight { + // Minimum execution time: 80_989 nanoseconds. + Weight::from_ref_time(83_605_753) + // Standard Error: 1_971 + .saturating_add(Weight::from_ref_time(942_989).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(12)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinValidatorBond (r:1 w:0) @@ -126,22 +130,22 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - // Minimum execution time: 57_094 nanoseconds. - Weight::from_ref_time(57_864_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 60_885 nanoseconds. + Weight::from_ref_time(61_554_000) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { - // Minimum execution time: 31_384 nanoseconds. - Weight::from_ref_time(29_774_315 as u64) - // Standard Error: 9_098 - .saturating_add(Weight::from_ref_time(6_166_589 as u64).saturating_mul(k as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(k as u64))) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(k as u64))) + // Minimum execution time: 33_903 nanoseconds. + Weight::from_ref_time(31_778_505) + // Standard Error: 6_146 + .saturating_add(Weight::from_ref_time(6_752_740).saturating_mul(k.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinNominatorBond (r:1 w:0) @@ -156,13 +160,13 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 60_432 nanoseconds. - Weight::from_ref_time(60_326_458 as u64) - // Standard Error: 4_664 - .saturating_add(Weight::from_ref_time(2_269_163 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 64_705 nanoseconds. + Weight::from_ref_time(64_102_064) + // Standard Error: 6_766 + .saturating_add(Weight::from_ref_time(2_431_890).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Validators (r:1 w:0) @@ -172,59 +176,59 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Minimum execution time: 55_783 nanoseconds. - Weight::from_ref_time(56_371_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 59_174 nanoseconds. + Weight::from_ref_time(59_942_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - // Minimum execution time: 15_149 nanoseconds. - Weight::from_ref_time(15_399_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_898 nanoseconds. + Weight::from_ref_time(16_056_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - // Minimum execution time: 21_225 nanoseconds. - Weight::from_ref_time(21_686_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 23_253 nanoseconds. + Weight::from_ref_time(23_642_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - // Minimum execution time: 3_772 nanoseconds. - Weight::from_ref_time(3_966_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_258 nanoseconds. + Weight::from_ref_time(4_437_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - // Minimum execution time: 3_959 nanoseconds. - Weight::from_ref_time(4_119_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_583 nanoseconds. + Weight::from_ref_time(4_788_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - // Minimum execution time: 3_808 nanoseconds. - Weight::from_ref_time(4_101_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_526 nanoseconds. + Weight::from_ref_time(4_789_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - // Minimum execution time: 3_910 nanoseconds. - Weight::from_ref_time(4_063_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_560 nanoseconds. + Weight::from_ref_time(4_746_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Invulnerables (r:0 w:1) /// The range of component `v` is `[0, 1000]`. fn set_invulnerables(v: u32, ) -> Weight { - // Minimum execution time: 4_072 nanoseconds. - Weight::from_ref_time(4_438_712 as u64) - // Standard Error: 27 - .saturating_add(Weight::from_ref_time(10_935 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_597 nanoseconds. + Weight::from_ref_time(4_979_598) + // Standard Error: 33 + .saturating_add(Weight::from_ref_time(13_875).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking SlashingSpans (r:1 w:0) @@ -241,23 +245,23 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { - // Minimum execution time: 67_363 nanoseconds. - Weight::from_ref_time(71_965_490 as u64) - // Standard Error: 1_701 - .saturating_add(Weight::from_ref_time(855_020 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 72_639 nanoseconds. + Weight::from_ref_time(78_014_035) + // Standard Error: 1_977 + .saturating_add(Weight::from_ref_time(935_656).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(12)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: Staking UnappliedSlashes (r:1 w:1) /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { - // Minimum execution time: 118_794 nanoseconds. - Weight::from_ref_time(1_322_525_367 as u64) - // Standard Error: 86_572 - .saturating_add(Weight::from_ref_time(7_367_119 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 122_368 nanoseconds. + Weight::from_ref_time(933_473_588) + // Standard Error: 59_092 + .saturating_add(Weight::from_ref_time(4_912_457).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking ErasValidatorReward (r:1 w:0) @@ -268,16 +272,16 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking ErasValidatorPrefs (r:1 w:0) // Storage: Staking Payee (r:1 w:0) // Storage: System Account (r:1 w:1) - /// The range of component `n` is `[0, 256]`. + /// The range of component `n` is `[0, 512]`. fn payout_stakers_dead_controller(n: u32, ) -> Weight { - // Minimum execution time: 93_351 nanoseconds. - Weight::from_ref_time(136_464_127 as u64) - // Standard Error: 14_412 - .saturating_add(Weight::from_ref_time(19_706_774 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(n as u64))) + // Minimum execution time: 111_492 nanoseconds. + Weight::from_ref_time(207_619_402) + // Standard Error: 17_422 + .saturating_add(Weight::from_ref_time(22_319_804).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) } // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking ErasValidatorReward (r:1 w:0) @@ -289,16 +293,16 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking Payee (r:1 w:0) // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) - /// The range of component `n` is `[0, 256]`. + /// The range of component `n` is `[0, 512]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { - // Minimum execution time: 110_077 nanoseconds. - Weight::from_ref_time(154_566_932 as u64) - // Standard Error: 24_823 - .saturating_add(Weight::from_ref_time(27_771_550 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(n as u64))) + // Minimum execution time: 128_057 nanoseconds. + Weight::from_ref_time(192_218_503) + // Standard Error: 29_376 + .saturating_add(Weight::from_ref_time(31_711_307).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -308,12 +312,12 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListBags (r:2 w:2) /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { - // Minimum execution time: 78_666 nanoseconds. - Weight::from_ref_time(80_640_795 as u64) - // Standard Error: 5_372 - .saturating_add(Weight::from_ref_time(24_280 as u64).saturating_mul(l as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 83_691 nanoseconds. + Weight::from_ref_time(85_457_544) + // Standard Error: 4_130 + .saturating_add(Weight::from_ref_time(32_449).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: System Account (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) @@ -330,16 +334,15 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking SpanSlash (r:0 w:1) /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { - // Minimum execution time: 77_329 nanoseconds. - Weight::from_ref_time(79_360_425 as u64) - // Standard Error: 1_804 - .saturating_add(Weight::from_ref_time(852_649 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 85_395 nanoseconds. + Weight::from_ref_time(84_844_648) + // Standard Error: 1_950 + .saturating_add(Weight::from_ref_time(953_435).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(12)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: Staking SlashingSpans (r:1 w:0) // Storage: VoterList ListBags (r:178 w:0) // Storage: VoterList ListNodes (r:101 w:0) // Storage: Staking Nominators (r:101 w:0) @@ -356,23 +359,23 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking ErasStakers (r:0 w:1) // Storage: Staking ErasTotalStake (r:0 w:1) // Storage: Staking ErasStartSessionIndex (r:0 w:1) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[1, 10]`. /// The range of component `n` is `[0, 100]`. fn new_era(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 436_511 nanoseconds. - Weight::from_ref_time(439_015_000 as u64) - // Standard Error: 1_814_104 - .saturating_add(Weight::from_ref_time(60_907_169 as u64).saturating_mul(v as u64)) - // Standard Error: 180_765 - .saturating_add(Weight::from_ref_time(12_850_120 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(186 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(v as u64))) + // Minimum execution time: 444_682 nanoseconds. + Weight::from_ref_time(445_632_000) + // Standard Error: 1_859_878 + .saturating_add(Weight::from_ref_time(60_717_370).saturating_mul(v.into())) + // Standard Error: 185_326 + .saturating_add(Weight::from_ref_time(13_355_900).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(185)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) } // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: Staking SlashingSpans (r:21 w:0) // Storage: VoterList ListBags (r:178 w:0) // Storage: VoterList ListNodes (r:1500 w:0) // Storage: Staking Nominators (r:1500 w:0) @@ -380,34 +383,33 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking Bonded (r:1500 w:0) // Storage: Staking Ledger (r:1500 w:0) // Storage: System BlockWeight (r:1 w:1) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[500, 1000]`. /// The range of component `n` is `[500, 1000]`. - /// The range of component `s` is `[1, 20]`. - fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { - // Minimum execution time: 25_507_250 nanoseconds. - Weight::from_ref_time(25_649_540_000 as u64) - // Standard Error: 501_634 - .saturating_add(Weight::from_ref_time(12_184_198 as u64).saturating_mul(v as u64)) - // Standard Error: 501_634 - .saturating_add(Weight::from_ref_time(10_028_550 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(181 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + fn get_npos_voters(v: u32, n: u32, ) -> Weight { + // Minimum execution time: 25_614_188 nanoseconds. + Weight::from_ref_time(25_803_581_000) + // Standard Error: 629_632 + .saturating_add(Weight::from_ref_time(6_922_005).saturating_mul(v.into())) + // Standard Error: 629_632 + .saturating_add(Weight::from_ref_time(2_982_329).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(180)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Staking CounterForValidators (r:1 w:0) // Storage: Staking Validators (r:501 w:0) // Storage: System BlockWeight (r:1 w:1) /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { - // Minimum execution time: 3_419_543 nanoseconds. - Weight::from_ref_time(112_565_697 as u64) - // Standard Error: 51_023 - .saturating_add(Weight::from_ref_time(6_975_412 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 3_650_499 nanoseconds. + Weight::from_ref_time(151_682_372) + // Standard Error: 39_270 + .saturating_add(Weight::from_ref_time(7_318_595).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking MinCommission (r:0 w:1) // Storage: Staking MinValidatorBond (r:0 w:1) @@ -416,9 +418,9 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_set() -> Weight { - // Minimum execution time: 6_970 nanoseconds. - Weight::from_ref_time(7_235_000 as u64) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 7_658 nanoseconds. + Weight::from_ref_time(7_982_000) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:0 w:1) // Storage: Staking MinValidatorBond (r:0 w:1) @@ -427,9 +429,9 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_remove() -> Weight { - // Minimum execution time: 6_338 nanoseconds. - Weight::from_ref_time(6_658_000 as u64) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 7_103 nanoseconds. + Weight::from_ref_time(7_388_000) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -442,17 +444,17 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - // Minimum execution time: 66_980 nanoseconds. - Weight::from_ref_time(67_728_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 70_308 nanoseconds. + Weight::from_ref_time(71_053_000) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:1 w:0) // Storage: Staking Validators (r:1 w:1) fn force_apply_min_commission() -> Weight { - // Minimum execution time: 14_843 nanoseconds. - Weight::from_ref_time(15_160_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_231 nanoseconds. + Weight::from_ref_time(15_756_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/pallet_timestamp.rs b/runtime/polkadot/src/weights/pallet_timestamp.rs index 4ab23d73847f..0ae225f14d59 100644 --- a/runtime/polkadot/src/weights/pallet_timestamp.rs +++ b/runtime/polkadot/src/weights/pallet_timestamp.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_timestamp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -47,13 +47,13 @@ impl pallet_timestamp::WeightInfo for WeightInfo { // Storage: Timestamp Now (r:1 w:1) // Storage: Babe CurrentSlot (r:1 w:0) fn set() -> Weight { - // Minimum execution time: 8_597 nanoseconds. - Weight::from_ref_time(8_891_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_277 nanoseconds. + Weight::from_ref_time(10_689_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } fn on_finalize() -> Weight { - // Minimum execution time: 3_577 nanoseconds. - Weight::from_ref_time(3_822_000 as u64) + // Minimum execution time: 4_656 nanoseconds. + Weight::from_ref_time(4_753_000) } } diff --git a/runtime/polkadot/src/weights/pallet_tips.rs b/runtime/polkadot/src/weights/pallet_tips.rs index d1ed1868bf98..219071603e84 100644 --- a/runtime/polkadot/src/weights/pallet_tips.rs +++ b/runtime/polkadot/src/weights/pallet_tips.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_tips` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -48,20 +48,20 @@ impl pallet_tips::WeightInfo for WeightInfo { // Storage: Tips Tips (r:1 w:1) /// The range of component `r` is `[0, 16384]`. fn report_awesome(r: u32, ) -> Weight { - // Minimum execution time: 28_913 nanoseconds. - Weight::from_ref_time(29_737_594 as u64) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(1_766 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 31_224 nanoseconds. + Weight::from_ref_time(32_186_925) + // Standard Error: 5 + .saturating_add(Weight::from_ref_time(1_855).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) fn retract_tip() -> Weight { - // Minimum execution time: 27_802 nanoseconds. - Weight::from_ref_time(28_839_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 30_391 nanoseconds. + Weight::from_ref_time(30_904_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Members (r:1 w:0) // Storage: Tips Reasons (r:1 w:1) @@ -69,25 +69,25 @@ impl pallet_tips::WeightInfo for WeightInfo { /// The range of component `r` is `[0, 16384]`. /// The range of component `t` is `[1, 13]`. fn tip_new(r: u32, t: u32, ) -> Weight { - // Minimum execution time: 21_545 nanoseconds. - Weight::from_ref_time(19_956_560 as u64) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(1_653 as u64).saturating_mul(r as u64)) - // Standard Error: 9_051 - .saturating_add(Weight::from_ref_time(273_746 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 23_918 nanoseconds. + Weight::from_ref_time(22_564_851) + // Standard Error: 5 + .saturating_add(Weight::from_ref_time(1_725).saturating_mul(r.into())) + // Standard Error: 7_486 + .saturating_add(Weight::from_ref_time(202_675).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Members (r:1 w:0) // Storage: Tips Tips (r:1 w:1) /// The range of component `t` is `[1, 13]`. fn tip(t: u32, ) -> Weight { - // Minimum execution time: 14_239 nanoseconds. - Weight::from_ref_time(14_637_145 as u64) - // Standard Error: 2_166 - .saturating_add(Weight::from_ref_time(160_076 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_366 nanoseconds. + Weight::from_ref_time(15_767_349) + // Standard Error: 1_953 + .saturating_add(Weight::from_ref_time(171_831).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Tips Tips (r:1 w:1) // Storage: PhragmenElection Members (r:1 w:0) @@ -95,22 +95,22 @@ impl pallet_tips::WeightInfo for WeightInfo { // Storage: Tips Reasons (r:0 w:1) /// The range of component `t` is `[1, 13]`. fn close_tip(t: u32, ) -> Weight { - // Minimum execution time: 42_946 nanoseconds. - Weight::from_ref_time(44_707_457 as u64) - // Standard Error: 6_862 - .saturating_add(Weight::from_ref_time(176_886 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 46_608 nanoseconds. + Weight::from_ref_time(48_091_893) + // Standard Error: 8_341 + .saturating_add(Weight::from_ref_time(163_813).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) /// The range of component `t` is `[1, 13]`. fn slash_tip(t: u32, ) -> Weight { - // Minimum execution time: 18_242 nanoseconds. - Weight::from_ref_time(18_986_836 as u64) - // Standard Error: 2_134 - .saturating_add(Weight::from_ref_time(44_433 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 19_869 nanoseconds. + Weight::from_ref_time(20_421_606) + // Standard Error: 6_113 + .saturating_add(Weight::from_ref_time(101_120).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/polkadot/src/weights/pallet_treasury.rs b/runtime/polkadot/src/weights/pallet_treasury.rs index 46275e5efeb7..c07ce930ba23 100644 --- a/runtime/polkadot/src/weights/pallet_treasury.rs +++ b/runtime/polkadot/src/weights/pallet_treasury.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_treasury` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -45,56 +45,58 @@ use sp_std::marker::PhantomData; pub struct WeightInfo(PhantomData); impl pallet_treasury::WeightInfo for WeightInfo { fn spend() -> Weight { - // Minimum execution time: 133 nanoseconds. - Weight::from_ref_time(163_000 as u64) + // Minimum execution time: 140 nanoseconds. + Weight::from_ref_time(188_000) } // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - // Minimum execution time: 25_090 nanoseconds. - Weight::from_ref_time(25_847_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 28_393 nanoseconds. + Weight::from_ref_time(29_088_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:1 w:1) fn reject_proposal() -> Weight { - // Minimum execution time: 36_063 nanoseconds. - Weight::from_ref_time(37_046_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 39_863 nanoseconds. + Weight::from_ref_time(40_525_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) /// The range of component `p` is `[0, 99]`. fn approve_proposal(p: u32, ) -> Weight { - // Minimum execution time: 9_380 nanoseconds. - Weight::from_ref_time(12_577_152 as u64) - // Standard Error: 1_050 - .saturating_add(Weight::from_ref_time(47_228 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_069 nanoseconds. + Weight::from_ref_time(13_628_936) + // Standard Error: 1_126 + .saturating_add(Weight::from_ref_time(51_043).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) fn remove_approval() -> Weight { - // Minimum execution time: 7_346 nanoseconds. - Weight::from_ref_time(7_802_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_527 nanoseconds. + Weight::from_ref_time(8_735_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } + // Storage: Treasury Inactive (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: Treasury Approvals (r:1 w:1) // Storage: Bounties BountyApprovals (r:1 w:1) // Storage: Treasury Proposals (r:2 w:2) // Storage: System Account (r:4 w:4) /// The range of component `p` is `[0, 100]`. fn on_initialize_proposals(p: u32, ) -> Weight { - // Minimum execution time: 33_748 nanoseconds. - Weight::from_ref_time(40_406_620 as u64) - // Standard Error: 16_502 - .saturating_add(Weight::from_ref_time(23_598_101 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(p as u64))) + // Minimum execution time: 41_280 nanoseconds. + Weight::from_ref_time(52_285_861) + // Standard Error: 22_867 + .saturating_add(Weight::from_ref_time(26_361_552).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(4)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(p.into()))) } } diff --git a/runtime/polkadot/src/weights/pallet_utility.rs b/runtime/polkadot/src/weights/pallet_utility.rs index 69e332d728f3..e9dc695d48c8 100644 --- a/runtime/polkadot/src/weights/pallet_utility.rs +++ b/runtime/polkadot/src/weights/pallet_utility.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_utility` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -46,31 +46,31 @@ pub struct WeightInfo(PhantomData); impl pallet_utility::WeightInfo for WeightInfo { /// The range of component `c` is `[0, 1000]`. fn batch(c: u32, ) -> Weight { - // Minimum execution time: 10_771 nanoseconds. - Weight::from_ref_time(16_778_329 as u64) - // Standard Error: 2_348 - .saturating_add(Weight::from_ref_time(3_322_539 as u64).saturating_mul(c as u64)) + // Minimum execution time: 12_269 nanoseconds. + Weight::from_ref_time(17_639_994) + // Standard Error: 2_151 + .saturating_add(Weight::from_ref_time(3_706_537).saturating_mul(c.into())) } fn as_derivative() -> Weight { - // Minimum execution time: 5_265 nanoseconds. - Weight::from_ref_time(5_423_000 as u64) + // Minimum execution time: 6_070 nanoseconds. + Weight::from_ref_time(6_170_000) } /// The range of component `c` is `[0, 1000]`. fn batch_all(c: u32, ) -> Weight { - // Minimum execution time: 10_866 nanoseconds. - Weight::from_ref_time(20_054_725 as u64) - // Standard Error: 3_715 - .saturating_add(Weight::from_ref_time(3_430_598 as u64).saturating_mul(c as u64)) + // Minimum execution time: 12_056 nanoseconds. + Weight::from_ref_time(17_407_117) + // Standard Error: 2_200 + .saturating_add(Weight::from_ref_time(3_896_277).saturating_mul(c.into())) } fn dispatch_as() -> Weight { - // Minimum execution time: 12_698 nanoseconds. - Weight::from_ref_time(12_946_000 as u64) + // Minimum execution time: 14_262 nanoseconds. + Weight::from_ref_time(14_706_000) } /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { - // Minimum execution time: 10_671 nanoseconds. - Weight::from_ref_time(14_320_668 as u64) - // Standard Error: 3_720 - .saturating_add(Weight::from_ref_time(3_299_555 as u64).saturating_mul(c as u64)) + // Minimum execution time: 12_345 nanoseconds. + Weight::from_ref_time(20_371_184) + // Standard Error: 2_353 + .saturating_add(Weight::from_ref_time(3_699_362).saturating_mul(c.into())) } } diff --git a/runtime/polkadot/src/weights/pallet_vesting.rs b/runtime/polkadot/src/weights/pallet_vesting.rs index 8140a7944b92..441a3d73d73d 100644 --- a/runtime/polkadot/src/weights/pallet_vesting.rs +++ b/runtime/polkadot/src/weights/pallet_vesting.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_vesting` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -49,28 +49,28 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_locked(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 36_655 nanoseconds. - Weight::from_ref_time(35_846_278 as u64) - // Standard Error: 1_164 - .saturating_add(Weight::from_ref_time(45_176 as u64).saturating_mul(l as u64)) - // Standard Error: 2_072 - .saturating_add(Weight::from_ref_time(73_745 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_107 nanoseconds. + Weight::from_ref_time(38_996_290) + // Standard Error: 1_136 + .saturating_add(Weight::from_ref_time(49_548).saturating_mul(l.into())) + // Standard Error: 2_021 + .saturating_add(Weight::from_ref_time(80_920).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_unlocked(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 36_392 nanoseconds. - Weight::from_ref_time(36_115_437 as u64) - // Standard Error: 1_029 - .saturating_add(Weight::from_ref_time(32_852 as u64).saturating_mul(l as u64)) - // Standard Error: 1_832 - .saturating_add(Weight::from_ref_time(51_682 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 39_803 nanoseconds. + Weight::from_ref_time(39_377_592) + // Standard Error: 1_339 + .saturating_add(Weight::from_ref_time(40_145).saturating_mul(l.into())) + // Standard Error: 2_382 + .saturating_add(Weight::from_ref_time(58_525).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -78,14 +78,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 36_298 nanoseconds. - Weight::from_ref_time(35_732_602 as u64) - // Standard Error: 1_118 - .saturating_add(Weight::from_ref_time(43_483 as u64).saturating_mul(l as u64)) - // Standard Error: 1_989 - .saturating_add(Weight::from_ref_time(73_636 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 39_745 nanoseconds. + Weight::from_ref_time(39_336_547) + // Standard Error: 1_617 + .saturating_add(Weight::from_ref_time(48_929).saturating_mul(l.into())) + // Standard Error: 2_877 + .saturating_add(Weight::from_ref_time(63_817).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -93,14 +93,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 36_437 nanoseconds. - Weight::from_ref_time(35_896_377 as u64) - // Standard Error: 1_037 - .saturating_add(Weight::from_ref_time(35_148 as u64).saturating_mul(l as u64)) - // Standard Error: 1_845 - .saturating_add(Weight::from_ref_time(52_168 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 39_623 nanoseconds. + Weight::from_ref_time(39_268_057) + // Standard Error: 1_169 + .saturating_add(Weight::from_ref_time(41_495).saturating_mul(l.into())) + // Standard Error: 2_079 + .saturating_add(Weight::from_ref_time(43_554).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:1 w:1) @@ -108,14 +108,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[0, 27]`. fn vested_transfer(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 51_425 nanoseconds. - Weight::from_ref_time(51_893_961 as u64) - // Standard Error: 2_087 - .saturating_add(Weight::from_ref_time(33_253 as u64).saturating_mul(l as u64)) - // Standard Error: 3_713 - .saturating_add(Weight::from_ref_time(30_498 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 54_568 nanoseconds. + Weight::from_ref_time(54_738_664) + // Standard Error: 1_909 + .saturating_add(Weight::from_ref_time(40_930).saturating_mul(l.into())) + // Standard Error: 3_396 + .saturating_add(Weight::from_ref_time(48_403).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:2 w:2) @@ -123,14 +123,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 50_485 nanoseconds. - Weight::from_ref_time(50_157_092 as u64) - // Standard Error: 1_939 - .saturating_add(Weight::from_ref_time(46_153 as u64).saturating_mul(l as u64)) - // Standard Error: 3_450 - .saturating_add(Weight::from_ref_time(62_537 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 53_651 nanoseconds. + Weight::from_ref_time(54_347_387) + // Standard Error: 1_974 + .saturating_add(Weight::from_ref_time(41_715).saturating_mul(l.into())) + // Standard Error: 3_512 + .saturating_add(Weight::from_ref_time(39_330).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -138,14 +138,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 37_645 nanoseconds. - Weight::from_ref_time(38_128_587 as u64) - // Standard Error: 1_361 - .saturating_add(Weight::from_ref_time(41_839 as u64).saturating_mul(l as u64)) - // Standard Error: 2_514 - .saturating_add(Weight::from_ref_time(28_665 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 41_189 nanoseconds. + Weight::from_ref_time(40_478_905) + // Standard Error: 1_471 + .saturating_add(Weight::from_ref_time(39_575).saturating_mul(l.into())) + // Standard Error: 2_716 + .saturating_add(Weight::from_ref_time(82_798).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -153,13 +153,13 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 37_771 nanoseconds. - Weight::from_ref_time(36_095_240 as u64) - // Standard Error: 1_698 - .saturating_add(Weight::from_ref_time(56_877 as u64).saturating_mul(l as u64)) - // Standard Error: 3_136 - .saturating_add(Weight::from_ref_time(91_827 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 40_880 nanoseconds. + Weight::from_ref_time(40_413_529) + // Standard Error: 1_052 + .saturating_add(Weight::from_ref_time(46_699).saturating_mul(l.into())) + // Standard Error: 1_943 + .saturating_add(Weight::from_ref_time(68_118).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/polkadot/src/weights/runtime_common_auctions.rs b/runtime/polkadot/src/weights/runtime_common_auctions.rs index e252c756f160..b5d384a15ce3 100644 --- a/runtime/polkadot/src/weights/runtime_common_auctions.rs +++ b/runtime/polkadot/src/weights/runtime_common_auctions.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::auctions` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -47,10 +47,10 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Auctions AuctionInfo (r:1 w:1) // Storage: Auctions AuctionCounter (r:1 w:1) fn new_auction() -> Weight { - // Minimum execution time: 16_106 nanoseconds. - Weight::from_ref_time(16_475_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 17_700 nanoseconds. + Weight::from_ref_time(18_419_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Paras ParaLifecycles (r:1 w:0) // Storage: Auctions AuctionCounter (r:1 w:0) @@ -60,10 +60,10 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Auctions ReservedAmounts (r:2 w:2) // Storage: System Account (r:1 w:1) fn bid() -> Weight { - // Minimum execution time: 68_962 nanoseconds. - Weight::from_ref_time(70_680_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 74_745 nanoseconds. + Weight::from_ref_time(76_728_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Auctions AuctionInfo (r:1 w:1) // Storage: Babe NextRandomness (r:1 w:0) @@ -78,19 +78,19 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar Paras (r:1 w:1) fn on_initialize() -> Weight { - // Minimum execution time: 14_584_826 nanoseconds. - Weight::from_ref_time(14_874_529_000 as u64) - .saturating_add(T::DbWeight::get().reads(3688 as u64)) - .saturating_add(T::DbWeight::get().writes(3683 as u64)) + // Minimum execution time: 15_485_064 nanoseconds. + Weight::from_ref_time(15_690_665_000) + .saturating_add(T::DbWeight::get().reads(3688)) + .saturating_add(T::DbWeight::get().writes(3683)) } // Storage: Auctions ReservedAmounts (r:37 w:36) // Storage: System Account (r:36 w:36) // Storage: Auctions Winning (r:0 w:3600) // Storage: Auctions AuctionInfo (r:0 w:1) fn cancel_auction() -> Weight { - // Minimum execution time: 4_529_670 nanoseconds. - Weight::from_ref_time(4_587_198_000 as u64) - .saturating_add(T::DbWeight::get().reads(73 as u64)) - .saturating_add(T::DbWeight::get().writes(3673 as u64)) + // Minimum execution time: 4_592_305 nanoseconds. + Weight::from_ref_time(4_646_078_000) + .saturating_add(T::DbWeight::get().reads(73)) + .saturating_add(T::DbWeight::get().writes(3673)) } } diff --git a/runtime/polkadot/src/weights/runtime_common_claims.rs b/runtime/polkadot/src/weights/runtime_common_claims.rs index 5dd38068392c..4b459266db6e 100644 --- a/runtime/polkadot/src/weights/runtime_common_claims.rs +++ b/runtime/polkadot/src/weights/runtime_common_claims.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::claims` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -52,20 +52,20 @@ impl runtime_common::claims::WeightInfo for WeightInfo< // Storage: System Account (r:1 w:0) // Storage: Balances Locks (r:1 w:1) fn claim() -> Weight { - // Minimum execution time: 141_861 nanoseconds. - Weight::from_ref_time(143_112_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 148_318 nanoseconds. + Weight::from_ref_time(150_804_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Claims Total (r:1 w:1) // Storage: Claims Vesting (r:0 w:1) // Storage: Claims Claims (r:0 w:1) // Storage: Claims Signing (r:0 w:1) fn mint_claim() -> Weight { - // Minimum execution time: 11_111 nanoseconds. - Weight::from_ref_time(11_500_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 12_261 nanoseconds. + Weight::from_ref_time(13_055_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Claims Claims (r:1 w:1) // Storage: Claims Signing (r:1 w:1) @@ -75,10 +75,10 @@ impl runtime_common::claims::WeightInfo for WeightInfo< // Storage: System Account (r:1 w:0) // Storage: Balances Locks (r:1 w:1) fn claim_attest() -> Weight { - // Minimum execution time: 143_305 nanoseconds. - Weight::from_ref_time(145_492_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 149_322 nanoseconds. + Weight::from_ref_time(152_156_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Claims Preclaims (r:1 w:1) // Storage: Claims Signing (r:1 w:1) @@ -89,19 +89,19 @@ impl runtime_common::claims::WeightInfo for WeightInfo< // Storage: System Account (r:1 w:0) // Storage: Balances Locks (r:1 w:1) fn attest() -> Weight { - // Minimum execution time: 64_919 nanoseconds. - Weight::from_ref_time(67_541_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 71_396 nanoseconds. + Weight::from_ref_time(73_484_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Claims Claims (r:1 w:2) // Storage: Claims Vesting (r:1 w:2) // Storage: Claims Signing (r:1 w:2) // Storage: Claims Preclaims (r:1 w:1) fn move_claim() -> Weight { - // Minimum execution time: 20_973 nanoseconds. - Weight::from_ref_time(21_378_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 23_164 nanoseconds. + Weight::from_ref_time(24_074_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(7)) } } diff --git a/runtime/polkadot/src/weights/runtime_common_crowdloan.rs b/runtime/polkadot/src/weights/runtime_common_crowdloan.rs index d16e92d158d6..bd64d4e5dcc5 100644 --- a/runtime/polkadot/src/weights/runtime_common_crowdloan.rs +++ b/runtime/polkadot/src/weights/runtime_common_crowdloan.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::crowdloan` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -49,75 +49,77 @@ impl runtime_common::crowdloan::WeightInfo for WeightIn // Storage: Paras ParaLifecycles (r:1 w:0) // Storage: Crowdloan NextFundIndex (r:1 w:1) fn create() -> Weight { - // Minimum execution time: 45_596 nanoseconds. - Weight::from_ref_time(47_441_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 48_503 nanoseconds. + Weight::from_ref_time(50_033_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: Slots Leases (r:1 w:0) // Storage: Auctions AuctionInfo (r:1 w:0) // Storage: System Account (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: Crowdloan EndingsCount (r:1 w:0) // Storage: Crowdloan NewRaise (r:1 w:1) // Storage: unknown [0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291] (r:1 w:1) fn contribute() -> Weight { - // Minimum execution time: 114_254 nanoseconds. - Weight::from_ref_time(115_945_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 121_844 nanoseconds. + Weight::from_ref_time(124_019_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: System Account (r:2 w:2) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: unknown [0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0] (r:1 w:1) fn withdraw() -> Weight { - // Minimum execution time: 53_866 nanoseconds. - Weight::from_ref_time(54_896_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 62_426 nanoseconds. + Weight::from_ref_time(63_506_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `k` is `[0, 1000]`. fn refund(k: u32, ) -> Weight { - // Minimum execution time: 53_179 nanoseconds. - Weight::from_ref_time(62_342_000 as u64) - // Standard Error: 13_922 - .saturating_add(Weight::from_ref_time(16_886_810 as u64).saturating_mul(k as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(k as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(k as u64))) + // Minimum execution time: 64_742 nanoseconds. + Weight::from_ref_time(64_919_000) + // Standard Error: 13_378 + .saturating_add(Weight::from_ref_time(19_461_805).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(3)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(k.into()))) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: System Account (r:1 w:1) fn dissolve() -> Weight { - // Minimum execution time: 35_590 nanoseconds. - Weight::from_ref_time(36_852_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 38_185 nanoseconds. + Weight::from_ref_time(39_279_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Crowdloan Funds (r:1 w:1) fn edit() -> Weight { - // Minimum execution time: 23_016 nanoseconds. - Weight::from_ref_time(24_040_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 25_099 nanoseconds. + Weight::from_ref_time(26_117_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Crowdloan Funds (r:1 w:0) // Storage: unknown [0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291] (r:1 w:1) fn add_memo() -> Weight { - // Minimum execution time: 32_720 nanoseconds. - Weight::from_ref_time(33_735_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 35_901 nanoseconds. + Weight::from_ref_time(36_621_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Crowdloan Funds (r:1 w:0) // Storage: Crowdloan NewRaise (r:1 w:1) fn poke() -> Weight { - // Minimum execution time: 24_996 nanoseconds. - Weight::from_ref_time(25_803_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_963 nanoseconds. + Weight::from_ref_time(27_564_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Auctions AuctionInfo (r:1 w:0) // Storage: Crowdloan EndingsCount (r:1 w:1) @@ -131,13 +133,13 @@ impl runtime_common::crowdloan::WeightInfo for WeightIn // Storage: System Account (r:2 w:2) /// The range of component `n` is `[2, 100]`. fn on_initialize(n: u32, ) -> Weight { - // Minimum execution time: 101_604 nanoseconds. - Weight::from_ref_time(9_838_939 as u64) - // Standard Error: 25_245 - .saturating_add(Weight::from_ref_time(38_848_064 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(n as u64))) + // Minimum execution time: 108_703 nanoseconds. + Weight::from_ref_time(13_096_416) + // Standard Error: 31_917 + .saturating_add(Weight::from_ref_time(42_551_929).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)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) } } diff --git a/runtime/polkadot/src/weights/runtime_common_paras_registrar.rs b/runtime/polkadot/src/weights/runtime_common_paras_registrar.rs index c9d09bce0b1f..ab2732d87a96 100644 --- a/runtime/polkadot/src/weights/runtime_common_paras_registrar.rs +++ b/runtime/polkadot/src/weights/runtime_common_paras_registrar.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::paras_registrar` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -48,10 +48,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:0) fn reserve() -> Weight { - // Minimum execution time: 30_439 nanoseconds. - Weight::from_ref_time(30_964_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 33_118 nanoseconds. + Weight::from_ref_time(33_824_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -64,10 +64,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras CurrentCodeHash (r:0 w:1) // Storage: Paras UpcomingParasGenesis (r:0 w:1) fn register() -> Weight { - // Minimum execution time: 7_299_578 nanoseconds. - Weight::from_ref_time(7_364_958_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 7_505_264 nanoseconds. + Weight::from_ref_time(7_578_949_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -80,10 +80,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras CurrentCodeHash (r:0 w:1) // Storage: Paras UpcomingParasGenesis (r:0 w:1) fn force_register() -> Weight { - // Minimum execution time: 7_280_658 nanoseconds. - Weight::from_ref_time(7_341_550_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 7_519_946 nanoseconds. + Weight::from_ref_time(7_580_737_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -92,10 +92,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar PendingSwap (r:0 w:1) fn deregister() -> Weight { - // Minimum execution time: 48_210 nanoseconds. - Weight::from_ref_time(49_518_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 50_019 nanoseconds. + Weight::from_ref_time(51_477_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Registrar Paras (r:1 w:0) // Storage: Paras ParaLifecycles (r:2 w:2) @@ -105,10 +105,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Crowdloan Funds (r:2 w:2) // Storage: Slots Leases (r:2 w:2) fn swap() -> Weight { - // Minimum execution time: 41_985 nanoseconds. - Weight::from_ref_time(43_341_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 45_054 nanoseconds. + Weight::from_ref_time(45_920_000) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras FutureCodeHash (r:1 w:1) // Storage: Paras UpgradeRestrictionSignal (r:1 w:1) @@ -123,20 +123,20 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras FutureCodeUpgrades (r:0 w:1) /// The range of component `b` is `[1, 3145728]`. fn schedule_code_upgrade(b: u32, ) -> Weight { - // Minimum execution time: 41_205 nanoseconds. - Weight::from_ref_time(41_445_000 as u64) + // Minimum execution time: 43_970 nanoseconds. + Weight::from_ref_time(44_368_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_274 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + .saturating_add(Weight::from_ref_time(2_368).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras Heads (r:0 w:1) /// The range of component `b` is `[1, 1048576]`. fn set_current_head(b: u32, ) -> Weight { - // Minimum execution time: 13_060 nanoseconds. - Weight::from_ref_time(13_271_000 as u64) + // Minimum execution time: 14_192 nanoseconds. + Weight::from_ref_time(14_474_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(903 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(966).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/runtime_common_slots.rs b/runtime/polkadot/src/weights/runtime_common_slots.rs index 3f8084b98ec1..3b8eb672abfd 100644 --- a/runtime/polkadot/src/weights/runtime_common_slots.rs +++ b/runtime/polkadot/src/weights/runtime_common_slots.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::slots` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -47,40 +47,40 @@ impl runtime_common::slots::WeightInfo for WeightInfo Weight { - // Minimum execution time: 29_416 nanoseconds. - Weight::from_ref_time(29_951_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 32_610 nanoseconds. + Weight::from_ref_time(33_161_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Paras Parachains (r:1 w:0) // Storage: Slots Leases (r:101 w:100) - // Storage: Paras ParaLifecycles (r:101 w:101) + // Storage: Paras ParaLifecycles (r:100 w:100) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar Paras (r:100 w:100) - /// The range of component `c` is `[1, 100]`. - /// The range of component `t` is `[1, 100]`. + /// 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 { - // Minimum execution time: 549_007 nanoseconds. - Weight::from_ref_time(553_067_000 as u64) - // Standard Error: 69_242 - .saturating_add(Weight::from_ref_time(1_978_452 as u64).saturating_mul(c as u64)) - // Standard Error: 69_242 - .saturating_add(Weight::from_ref_time(11_522_846 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(t as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(t as u64))) + // Minimum execution time: 565_673 nanoseconds. + Weight::from_ref_time(568_063_000) + // Standard Error: 71_388 + .saturating_add(Weight::from_ref_time(2_363_534).saturating_mul(c.into())) + // Standard Error: 71_388 + .saturating_add(Weight::from_ref_time(12_473_232).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().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()))) } // Storage: Slots Leases (r:1 w:1) // Storage: System Account (r:8 w:8) fn clear_all_leases() -> Weight { - // Minimum execution time: 89_790 nanoseconds. - Weight::from_ref_time(90_964_000 as u64) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 96_528 nanoseconds. + Weight::from_ref_time(97_910_000) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(9)) } // Storage: Slots Leases (r:1 w:0) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -88,9 +88,9 @@ impl runtime_common::slots::WeightInfo for WeightInfo Weight { - // Minimum execution time: 28_418 nanoseconds. - Weight::from_ref_time(29_017_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 29_991 nanoseconds. + Weight::from_ref_time(31_232_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/polkadot/src/weights/runtime_parachains_configuration.rs b/runtime/polkadot/src/weights/runtime_parachains_configuration.rs index f4d7607236b7..7008c0233f10 100644 --- a/runtime/polkadot/src/weights/runtime_parachains_configuration.rs +++ b/runtime/polkadot/src/weights/runtime_parachains_configuration.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::configuration` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -49,54 +49,54 @@ impl runtime_parachains::configuration::WeightInfo for // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_block_number() -> Weight { - // Minimum execution time: 10_286 nanoseconds. - Weight::from_ref_time(10_978_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_758 nanoseconds. + Weight::from_ref_time(12_127_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_u32() -> Weight { - // Minimum execution time: 10_568 nanoseconds. - Weight::from_ref_time(11_052_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_695 nanoseconds. + Weight::from_ref_time(12_118_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_option_u32() -> Weight { - // Minimum execution time: 10_569 nanoseconds. - Weight::from_ref_time(10_956_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_542 nanoseconds. + Weight::from_ref_time(12_035_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_weight() -> Weight { - // Minimum execution time: 11_005 nanoseconds. - Weight::from_ref_time(11_394_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_899 nanoseconds. + Weight::from_ref_time(12_349_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Benchmark Override (r:0 w:0) fn set_hrmp_open_request_ttl() -> Weight { // Minimum execution time: 2_000_000_000 nanoseconds. - Weight::from_ref_time(2_000_000_000_000 as u64) + Weight::from_ref_time(2_000_000_000_000) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_balance() -> Weight { - // Minimum execution time: 10_792 nanoseconds. - Weight::from_ref_time(11_341_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_749 nanoseconds. + Weight::from_ref_time(12_199_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/runtime_parachains_disputes.rs b/runtime/polkadot/src/weights/runtime_parachains_disputes.rs index cf30508fb78a..d77c97d8e161 100644 --- a/runtime/polkadot/src/weights/runtime_parachains_disputes.rs +++ b/runtime/polkadot/src/weights/runtime_parachains_disputes.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::disputes` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -46,8 +46,8 @@ pub struct WeightInfo(PhantomData); impl runtime_parachains::disputes::WeightInfo for WeightInfo { // Storage: ParasDisputes Frozen (r:0 w:1) fn force_unfreeze() -> Weight { - // Minimum execution time: 3_857 nanoseconds. - Weight::from_ref_time(4_013_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_427 nanoseconds. + Weight::from_ref_time(4_596_000) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/runtime_parachains_hrmp.rs b/runtime/polkadot/src/weights/runtime_parachains_hrmp.rs index b3ddc8251898..f8abbd7b79c7 100644 --- a/runtime/polkadot/src/weights/runtime_parachains_hrmp.rs +++ b/runtime/polkadot/src/weights/runtime_parachains_hrmp.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::hrmp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -54,10 +54,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_init_open_channel() -> Weight { - // Minimum execution time: 38_437 nanoseconds. - Weight::from_ref_time(39_247_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 42_160 nanoseconds. + Weight::from_ref_time(42_643_000) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) @@ -67,10 +67,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_accept_open_channel() -> Weight { - // Minimum execution time: 37_957 nanoseconds. - Weight::from_ref_time(38_348_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 41_408 nanoseconds. + Weight::from_ref_time(41_827_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Hrmp HrmpChannels (r:1 w:0) // Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) @@ -79,10 +79,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_close_channel() -> Weight { - // Minimum execution time: 34_872 nanoseconds. - Weight::from_ref_time(35_365_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 37_916 nanoseconds. + Weight::from_ref_time(38_381_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127) // Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1) @@ -93,18 +93,18 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// 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 { - // Minimum execution time: 855_200 nanoseconds. - Weight::from_ref_time(858_064_000 as u64) - // Standard Error: 77_590 - .saturating_add(Weight::from_ref_time(2_626_939 as u64).saturating_mul(i as u64)) - // Standard Error: 77_590 - .saturating_add(Weight::from_ref_time(2_688_959 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(e as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(e as u64))) + // Minimum execution time: 912_589 nanoseconds. + Weight::from_ref_time(920_486_000) + // Standard Error: 83_269 + .saturating_add(Weight::from_ref_time(2_815_102).saturating_mul(i.into())) + // Standard Error: 83_269 + .saturating_add(Weight::from_ref_time(2_944_576).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()))) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(i.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(e.into()))) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0) @@ -117,14 +117,14 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpChannels (r:0 w:2) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_open(c: u32, ) -> Weight { - // Minimum execution time: 8_849 nanoseconds. - Weight::from_ref_time(9_014_000 as u64) - // Standard Error: 7_867 - .saturating_add(Weight::from_ref_time(15_479_468 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((7 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((6 as u64).saturating_mul(c as u64))) + // Minimum execution time: 9_715 nanoseconds. + Weight::from_ref_time(9_806_000) + // Standard Error: 9_212 + .saturating_add(Weight::from_ref_time(16_505_526).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()))) } // Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0) // Storage: Hrmp HrmpChannels (r:2 w:2) @@ -134,39 +134,39 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpChannelContents (r:0 w:2) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_close(c: u32, ) -> Weight { - // Minimum execution time: 5_664 nanoseconds. - Weight::from_ref_time(110_996 as u64) - // Standard Error: 10_270 - .saturating_add(Weight::from_ref_time(9_388_103 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((5 as u64).saturating_mul(c as u64))) + // Minimum execution time: 6_624 nanoseconds. + Weight::from_ref_time(6_791_000) + // Standard Error: 6_263 + .saturating_add(Weight::from_ref_time(10_201_172).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()))) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) /// The range of component `c` is `[0, 128]`. fn hrmp_cancel_open_request(c: u32, ) -> Weight { - // Minimum execution time: 24_259 nanoseconds. - Weight::from_ref_time(30_040_803 as u64) - // Standard Error: 1_283 - .saturating_add(Weight::from_ref_time(93_082 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 26_466 nanoseconds. + Weight::from_ref_time(32_211_795) + // Standard Error: 1_271 + .saturating_add(Weight::from_ref_time(95_619).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) /// The range of component `c` is `[0, 128]`. fn clean_open_channel_requests(c: u32, ) -> Weight { - // Minimum execution time: 4_103 nanoseconds. - Weight::from_ref_time(1_950_408 as u64) - // Standard Error: 3_739 - .saturating_add(Weight::from_ref_time(2_548_927 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + // Minimum execution time: 4_860 nanoseconds. + Weight::from_ref_time(3_362_442) + // Standard Error: 3_610 + .saturating_add(Weight::from_ref_time(2_656_647).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()))) } // Storage: Paras ParaLifecycles (r:2 w:0) // Storage: Configuration ActiveConfig (r:1 w:0) @@ -180,9 +180,9 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) fn force_open_hrmp_channel() -> Weight { - // Minimum execution time: 49_505 nanoseconds. - Weight::from_ref_time(51_263_000 as u64) - .saturating_add(T::DbWeight::get().reads(14 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 53_717 nanoseconds. + Weight::from_ref_time(54_396_000) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(8)) } } diff --git a/runtime/polkadot/src/weights/runtime_parachains_initializer.rs b/runtime/polkadot/src/weights/runtime_parachains_initializer.rs index 37ffc7e53fe0..97e149aca3e1 100644 --- a/runtime/polkadot/src/weights/runtime_parachains_initializer.rs +++ b/runtime/polkadot/src/weights/runtime_parachains_initializer.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::initializer` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -47,11 +47,11 @@ impl runtime_parachains::initializer::WeightInfo for We // Storage: System Digest (r:1 w:1) /// The range of component `d` is `[0, 65536]`. fn force_approve(d: u32, ) -> Weight { - // Minimum execution time: 7_037 nanoseconds. - Weight::from_ref_time(9_934_606 as u64) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(1_316 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_317 nanoseconds. + Weight::from_ref_time(11_009_964) + // Standard Error: 5 + .saturating_add(Weight::from_ref_time(1_314).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/polkadot/src/weights/runtime_parachains_paras.rs b/runtime/polkadot/src/weights/runtime_parachains_paras.rs index 3ae8038360e6..f44e3fda2e9b 100644 --- a/runtime/polkadot/src/weights/runtime_parachains_paras.rs +++ b/runtime/polkadot/src/weights/runtime_parachains_paras.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::paras` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -52,21 +52,21 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras CodeByHash (r:0 w:1) /// The range of component `c` is `[1, 3145728]`. fn force_set_current_code(c: u32, ) -> Weight { - // Minimum execution time: 33_710 nanoseconds. - Weight::from_ref_time(33_974_000 as u64) + // Minimum execution time: 36_730 nanoseconds. + Weight::from_ref_time(37_121_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_259 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + .saturating_add(Weight::from_ref_time(2_354).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) /// The range of component `s` is `[1, 1048576]`. fn force_set_current_head(s: u32, ) -> Weight { - // Minimum execution time: 12_424 nanoseconds. - Weight::from_ref_time(12_683_000 as u64) + // Minimum execution time: 13_657 nanoseconds. + Weight::from_ref_time(13_898_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(904 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(959).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Paras FutureCodeHash (r:1 w:1) @@ -81,61 +81,61 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras UpgradeRestrictionSignal (r:0 w:1) /// The range of component `c` is `[1, 3145728]`. fn force_schedule_code_upgrade(c: u32, ) -> Weight { - // Minimum execution time: 56_907 nanoseconds. - Weight::from_ref_time(57_326_000 as u64) - // Standard Error: 2 - .saturating_add(Weight::from_ref_time(2_289 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 62_202 nanoseconds. + Weight::from_ref_time(62_741_000) + // Standard Error: 1 + .saturating_add(Weight::from_ref_time(2_374).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras FutureCodeUpgrades (r:1 w:0) // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) /// The range of component `s` is `[1, 1048576]`. fn force_note_new_head(s: u32, ) -> Weight { - // Minimum execution time: 18_297 nanoseconds. - Weight::from_ref_time(18_498_000 as u64) + // Minimum execution time: 19_306 nanoseconds. + Weight::from_ref_time(19_573_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(903 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(961).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) // Storage: Paras ActionsQueue (r:1 w:1) fn force_queue_action() -> Weight { - // Minimum execution time: 22_688 nanoseconds. - Weight::from_ref_time(23_185_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 24_330 nanoseconds. + Weight::from_ref_time(24_697_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras PvfActiveVoteMap (r:1 w:0) // Storage: Paras CodeByHash (r:1 w:1) /// The range of component `c` is `[1, 3145728]`. fn add_trusted_validation_code(c: u32, ) -> Weight { - // Minimum execution time: 8_283 nanoseconds. - Weight::from_ref_time(8_421_000 as u64) + // Minimum execution time: 9_281 nanoseconds. + Weight::from_ref_time(9_463_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_269 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(2_359).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras CodeByHashRefs (r:1 w:0) // Storage: Paras CodeByHash (r:0 w:1) fn poke_unused_validation_code() -> Weight { - // Minimum execution time: 6_271 nanoseconds. - Weight::from_ref_time(6_442_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 7_078 nanoseconds. + Weight::from_ref_time(7_538_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) // Storage: Paras PvfActiveVoteMap (r:1 w:1) fn include_pvf_check_statement() -> Weight { - // Minimum execution time: 92_849 nanoseconds. - Weight::from_ref_time(95_135_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 93_834 nanoseconds. + Weight::from_ref_time(97_594_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) @@ -146,10 +146,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: System Digest (r:1 w:1) // Storage: Paras FutureCodeUpgrades (r:0 w:100) fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { - // Minimum execution time: 609_526 nanoseconds. - Weight::from_ref_time(615_900_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(104 as u64)) + // Minimum execution time: 668_112 nanoseconds. + Weight::from_ref_time(678_124_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(104)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) @@ -161,10 +161,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras UpgradeGoAheadSignal (r:0 w:100) // Storage: Paras FutureCodeHash (r:0 w:100) fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { - // Minimum execution time: 578_583 nanoseconds. - Weight::from_ref_time(583_643_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(204 as u64)) + // Minimum execution time: 624_859 nanoseconds. + Weight::from_ref_time(634_113_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(204)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) @@ -173,10 +173,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras PvfActiveVoteList (r:1 w:1) // Storage: Paras ActionsQueue (r:1 w:1) fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { - // Minimum execution time: 478_058 nanoseconds. - Weight::from_ref_time(484_139_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 521_765 nanoseconds. + Weight::from_ref_time(527_269_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) @@ -189,9 +189,9 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras CurrentCodeHash (r:0 w:100) // Storage: Paras UpcomingParasGenesis (r:0 w:100) fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { - // Minimum execution time: 645_823 nanoseconds. - Weight::from_ref_time(651_570_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(304 as u64)) + // Minimum execution time: 699_263 nanoseconds. + Weight::from_ref_time(705_929_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(304)) } } diff --git a/runtime/polkadot/src/weights/runtime_parachains_paras_inherent.rs b/runtime/polkadot/src/weights/runtime_parachains_paras_inherent.rs index 5bdb5a69cf9e..ada45c6efe75 100644 --- a/runtime/polkadot/src/weights/runtime_parachains_paras_inherent.rs +++ b/runtime/polkadot/src/weights/runtime_parachains_paras_inherent.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::paras_inherent` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm6`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("polkadot-dev"), DB CACHE: 1024 @@ -78,12 +78,12 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) /// The range of component `v` is `[10, 200]`. fn enter_variable_disputes(v: u32, ) -> Weight { - // Minimum execution time: 807_698 nanoseconds. - Weight::from_ref_time(341_101_514 as u64) - // Standard Error: 19_162 - .saturating_add(Weight::from_ref_time(48_114_458 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(30 as u64)) - .saturating_add(T::DbWeight::get().writes(18 as u64)) + // Minimum execution time: 819_257 nanoseconds. + Weight::from_ref_time(370_630_260) + // Standard Error: 21_227 + .saturating_add(Weight::from_ref_time(47_673_829).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(30)) + .saturating_add(T::DbWeight::get().writes(18)) } // Storage: ParaInherent Included (r:1 w:1) // Storage: System ParentHash (r:1 w:0) @@ -117,10 +117,10 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) fn enter_bitfields() -> Weight { - // Minimum execution time: 323_534 nanoseconds. - Weight::from_ref_time(331_378_000 as u64) - .saturating_add(T::DbWeight::get().reads(27 as u64)) - .saturating_add(T::DbWeight::get().writes(17 as u64)) + // Minimum execution time: 342_960 nanoseconds. + Weight::from_ref_time(351_793_000) + .saturating_add(T::DbWeight::get().reads(27)) + .saturating_add(T::DbWeight::get().writes(17)) } // Storage: ParaInherent Included (r:1 w:1) // Storage: System ParentHash (r:1 w:0) @@ -156,12 +156,12 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) /// The range of component `v` is `[101, 200]`. fn enter_backed_candidates_variable(v: u32, ) -> Weight { - // Minimum execution time: 5_638_372 nanoseconds. - Weight::from_ref_time(862_604_609 as u64) - // Standard Error: 44_586 - .saturating_add(Weight::from_ref_time(47_777_322 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(30 as u64)) - .saturating_add(T::DbWeight::get().writes(16 as u64)) + // Minimum execution time: 5_654_868 nanoseconds. + Weight::from_ref_time(888_144_567) + // Standard Error: 44_714 + .saturating_add(Weight::from_ref_time(47_610_457).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(30)) + .saturating_add(T::DbWeight::get().writes(16)) } // Storage: ParaInherent Included (r:1 w:1) // Storage: System ParentHash (r:1 w:0) @@ -198,9 +198,9 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) fn enter_backed_candidate_code_upgrade() -> Weight { - // Minimum execution time: 37_925_898 nanoseconds. - Weight::from_ref_time(38_042_479_000 as u64) - .saturating_add(T::DbWeight::get().reads(32 as u64)) - .saturating_add(T::DbWeight::get().writes(16 as u64)) + // Minimum execution time: 39_513_215 nanoseconds. + Weight::from_ref_time(39_820_619_000) + .saturating_add(T::DbWeight::get().reads(32)) + .saturating_add(T::DbWeight::get().writes(16)) } } diff --git a/runtime/polkadot/src/xcm_config.rs b/runtime/polkadot/src/xcm_config.rs index 846d98a59d99..39f7a337479a 100644 --- a/runtime/polkadot/src/xcm_config.rs +++ b/runtime/polkadot/src/xcm_config.rs @@ -107,10 +107,12 @@ pub type XcmRouter = ( parameter_types! { pub const Polkadot: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(DotLocation::get()) }); pub const PolkadotForStatemint: (MultiAssetFilter, MultiLocation) = (Polkadot::get(), Parachain(1000).into()); + pub const PolkadotForCollectives: (MultiAssetFilter, MultiLocation) = (Polkadot::get(), Parachain(1001).into()); } -/// Polkadot Relay recognizes/respects the Statemint chain as a teleporter. -pub type TrustedTeleporters = (xcm_builder::Case,); +/// Polkadot Relay recognizes/respects System parachains as teleporters. +pub type TrustedTeleporters = + (xcm_builder::Case, xcm_builder::Case); match_types! { pub type OnlyParachains: impl Contains = { diff --git a/runtime/rococo/Cargo.toml b/runtime/rococo/Cargo.toml index 788f2d206450..7f3245528c42 100644 --- a/runtime/rococo/Cargo.toml +++ b/runtime/rococo/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "rococo-runtime" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" build = "build.rs" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive", "max-encoded-len"] } @@ -14,70 +14,71 @@ serde_derive = { version = "1.0.117", optional = true } static_assertions = "1.1.0" smallvec = "1.8.0" -authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -beefy-merkle-tree = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, package = "sp-beefy" , branch = "polkadot-v0.9.36" } +beefy-merkle-tree = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } rococo-runtime-constants = { package = "rococo-runtime-constants", path = "./constants", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-beefy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-child-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-gilt = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-identity = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-im-online = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-mmr = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-recovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-society = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system = {git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-tips = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-beefy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-child-bounties = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-state-trie-migration = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-identity = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-im-online = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-mmr = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-nis = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-recovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-society = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system = {git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-tips = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } pallet-xcm = { path = "../../xcm/pallet-xcm", default-features = false } pallet-xcm-benchmarks = { path = "../../xcm/pallet-xcm-benchmarks", default-features = false, optional = true } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -hex-literal = { version = "0.3.4", optional = true } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +hex-literal = { version = "0.3.4" } runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false } runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parachains", default-features = false } @@ -89,15 +90,14 @@ xcm-executor = { package = "xcm-executor", path = "../../xcm/xcm-executor", defa xcm-builder = { package = "xcm-builder", path = "../../xcm/xcm-builder", default-features = false } [dev-dependencies] -hex-literal = "0.3.4" tiny-keccak = { version = "2.0.2", features = ["keccak"] } -keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } separator = "0.4.1" serde_json = "1.0.81" [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = ["std"] @@ -124,12 +124,13 @@ std = [ "pallet-beefy-mmr/std", "pallet-bounties/std", "pallet-child-bounties/std", + "pallet-state-trie-migration/std", "pallet-transaction-payment/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-collective/std", "pallet-elections-phragmen/std", "pallet-democracy/std", - "pallet-gilt/std", + "pallet-nis/std", "pallet-grandpa/std", "pallet-identity/std", "pallet-im-online/std", @@ -187,7 +188,7 @@ runtime-benchmarks = [ "pallet-collective/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", - "pallet-gilt/runtime-benchmarks", + "pallet-nis/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-identity/runtime-benchmarks", "pallet-im-online/runtime-benchmarks", @@ -207,7 +208,6 @@ runtime-benchmarks = [ "pallet-vesting/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", - "hex-literal", "xcm-builder/runtime-benchmarks", "runtime-parachains/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", diff --git a/runtime/rococo/constants/Cargo.toml b/runtime/rococo/constants/Cargo.toml index 6dd84ac500b7..b2c71830bc32 100644 --- a/runtime/rococo/constants/Cargo.toml +++ b/runtime/rococo/constants/Cargo.toml @@ -1,18 +1,18 @@ [package] name = "rococo-runtime-constants" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] smallvec = "1.8.0" -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } primitives = { package = "polkadot-primitives", path = "../../../primitives", default-features = false } runtime-common = { package = "polkadot-runtime-common", path = "../../common", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-weights = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/runtime/rococo/constants/src/weights/block_weights.rs b/runtime/rococo/constants/src/weights/block_weights.rs index b1531e6a5a1e..d16f4082da13 100644 --- a/runtime/rococo/constants/src/weights/block_weights.rs +++ b/runtime/rococo/constants/src/weights/block_weights.rs @@ -14,7 +14,7 @@ // 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: 2022-10-25 (Y/M/D) +//! DATE: 2022-12-16 (Y/M/D) //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `block`, LONG-NAME: `BlockExecution`, RUNTIME: `Development` @@ -35,23 +35,24 @@ // --header=./file_header.txt use sp_core::parameter_types; -use sp_weights::{constants::WEIGHT_PER_NANOS, Weight}; +use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; parameter_types! { /// Time to execute an empty block. /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 5_028_795, 5_299_376 - /// Average: 5_112_220 - /// Median: 5_112_316 - /// Std-Dev: 66397.03 + /// Min, Max: 448_169, 501_847 + /// Average: 458_063 + /// Median: 451_532 + /// Std-Dev: 12761.42 /// /// Percentiles nanoseconds: - /// 99th: 5_294_206 - /// 95th: 5_220_039 - /// 75th: 5_149_614 - pub const BlockExecutionWeight: Weight = WEIGHT_PER_NANOS.saturating_mul(5_112_220); + /// 99th: 492_121 + /// 95th: 482_566 + /// 75th: 457_121 + pub const BlockExecutionWeight: Weight = + Weight::from_ref_time(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(458_063)); } #[cfg(test)] @@ -67,12 +68,12 @@ mod test_weights { // At least 100 µs. assert!( - w.ref_time() >= 100u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 100 µs." ); // At most 50 ms. assert!( - w.ref_time() <= 50u64 * constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms." ); } diff --git a/runtime/rococo/constants/src/weights/extrinsic_weights.rs b/runtime/rococo/constants/src/weights/extrinsic_weights.rs index fcca6b74ccee..632404657fdf 100644 --- a/runtime/rococo/constants/src/weights/extrinsic_weights.rs +++ b/runtime/rococo/constants/src/weights/extrinsic_weights.rs @@ -14,7 +14,7 @@ // 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: 2022-10-25 (Y/M/D) +//! DATE: 2022-12-16 (Y/M/D) //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `extrinsic`, LONG-NAME: `ExtrinsicBase`, RUNTIME: `Development` @@ -35,23 +35,24 @@ // --header=./file_header.txt use sp_core::parameter_types; -use sp_weights::{constants::WEIGHT_PER_NANOS, Weight}; +use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; parameter_types! { /// Time to execute a NO-OP extrinsic, for example `System::remark`. /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 88_402, 90_261 - /// Average: 88_851 - /// Median: 88_823 - /// Std-Dev: 315.42 + /// Min, Max: 88_825, 91_178 + /// Average: 89_399 + /// Median: 89_384 + /// Std-Dev: 376.08 /// /// Percentiles nanoseconds: - /// 99th: 90_200 - /// 95th: 89_354 - /// 75th: 88_922 - pub const ExtrinsicBaseWeight: Weight = WEIGHT_PER_NANOS.saturating_mul(88_851); + /// 99th: 90_800 + /// 95th: 90_033 + /// 75th: 89_476 + pub const ExtrinsicBaseWeight: Weight = + Weight::from_ref_time(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(89_399)); } #[cfg(test)] @@ -67,12 +68,12 @@ mod test_weights { // At least 10 µs. assert!( - w.ref_time() >= 10u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs." ); // At most 1 ms. assert!( - w.ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms." ); } diff --git a/runtime/rococo/constants/src/weights/paritydb_weights.rs b/runtime/rococo/constants/src/weights/paritydb_weights.rs index dca7d348310c..4338d928d807 100644 --- a/runtime/rococo/constants/src/weights/paritydb_weights.rs +++ b/runtime/rococo/constants/src/weights/paritydb_weights.rs @@ -25,8 +25,8 @@ pub mod constants { /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights /// are available for brave runtime engineers who may want to try this out as default. pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 8_000 * constants::WEIGHT_PER_NANOS.ref_time(), - write: 50_000 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 8_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 50_000 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -42,20 +42,20 @@ pub mod constants { fn sane() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/rococo/constants/src/weights/rocksdb_weights.rs b/runtime/rococo/constants/src/weights/rocksdb_weights.rs index 87867ebfe177..1d115d963fac 100644 --- a/runtime/rococo/constants/src/weights/rocksdb_weights.rs +++ b/runtime/rococo/constants/src/weights/rocksdb_weights.rs @@ -25,8 +25,8 @@ pub mod constants { /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout /// the runtime. pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 25_000 * constants::WEIGHT_PER_NANOS.ref_time(), - write: 100_000 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 25_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 100_000 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -42,20 +42,20 @@ pub mod constants { fn sane() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/rococo/src/bridge_messages.rs b/runtime/rococo/src/bridge_messages.rs deleted file mode 100644 index 5302768b84d3..000000000000 --- a/runtime/rococo/src/bridge_messages.rs +++ /dev/null @@ -1,527 +0,0 @@ -// Copyright 2020 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 . - -//! Over-bridge messaging support for Rococo <> Wococo bridge. - -pub use self::{at_rococo::*, at_wococo::*}; - -use crate::{Balances, Runtime}; - -use bp_messages::{ - source_chain::{SenderOrigin, TargetHeaderChain}, - target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, -}; -use bp_rococo::{Balance, Rococo, EXTRA_STORAGE_PROOF_SIZE, MAXIMAL_ENCODED_ACCOUNT_ID_SIZE}; -use bp_runtime::{Chain, ChainId, ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; -use bridge_runtime_common::messages::{ - source as messages_source, target as messages_target, transaction_payment, - BridgedChainWithMessages, ChainWithMessages, MessageBridge, MessageTransaction, - ThisChainWithMessages, -}; -use frame_support::{ - traits::Get, - weights::{Weight, WeightToFee as WeightToFeeT}, - RuntimeDebug, -}; -use rococo_runtime_constants::fee::WeightToFee; -use sp_runtime::FixedU128; -use sp_std::{marker::PhantomData, ops::RangeInclusive}; - -/// Maximal number of pending outbound messages. -const MAXIMAL_PENDING_MESSAGES_AT_OUTBOUND_LANE: MessageNonce = - bp_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; -/// Maximal weight of single message delivery confirmation transaction on Rococo/Wococo chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` weight formula -/// computation for the case when single message is confirmed. The result then must be rounded up to account -/// possible future runtime upgrades. -const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; -/// Increase of delivery transaction weight on Rococo/Wococo chain with every additional message byte. -/// -/// This value is a result of `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The -/// result then must be rounded up to account possible future runtime upgrades. -const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; -/// Weight of single regular message delivery transaction on Rococo/Wococo chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. -/// The message must have dispatch weight set to zero. The result then must be rounded up to account -/// possible future runtime upgrades. -const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; -/// Weight of pay-dispatch-fee operation for inbound messages at Rococo/Wococo chain. -/// -/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` -/// call for your chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper. -const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; -/// Number of bytes, included in the signed Rococo/Wococo transaction apart from the encoded call itself. -/// -/// Can be computed by subtracting encoded call size from raw transaction size. -const TX_EXTRA_BYTES: u32 = 130; - -/// Rococo chain as it is seen at Rococo. -pub type RococoAtRococo = - RococoLikeChain; - -/// Rococo chain as it is seen at Wococo. -pub type RococoAtWococo = - RococoLikeChain; - -/// Wococo chain as it is seen at Wococo. -pub type WococoAtWococo = - RococoLikeChain; - -/// Wococo chain as it is seen at Rococo. -pub type WococoAtRococo = - RococoLikeChain; - -/// Rococo/Wococo chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct RococoLikeChain { - _bridge_definition: PhantomData, - _at_this_chain_grandpa_pallet_instance: PhantomData, -} - -impl ChainWithMessages for RococoLikeChain { - type Hash = crate::Hash; - type AccountId = crate::AccountId; - type Signer = primitives::v2::AccountPublic; - type Signature = crate::Signature; - type Weight = Weight; - type Balance = Balance; -} - -impl ThisChainWithMessages for RococoLikeChain { - type Origin = crate::Origin; - type Call = crate::Call; - - fn is_message_accepted(_submitter: &crate::Origin, lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MAXIMAL_PENDING_MESSAGES_AT_OUTBOUND_LANE - } - - fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = InboundLaneData::::encoded_size_hint( - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - 1, - 1, - ) - .unwrap_or(u32::MAX); - - MessageTransaction { - dispatch_weight: MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - size: inbound_data_size - .saturating_add(EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(TX_EXTRA_BYTES), - } - } - - fn transaction_payment(transaction: MessageTransaction) -> Balance { - // current fee multiplier is used here - transaction_payment( - crate::BlockWeights::get() - .get(frame_support::weights::DispatchClass::Normal) - .base_extrinsic, - crate::TransactionByteFee::get(), - pallet_transaction_payment::Pallet::::next_fee_multiplier(), - |weight| WeightToFee::weight_to_fee(&weight), - transaction, - ) - } -} - -impl BridgedChainWithMessages for RococoLikeChain { - fn maximal_extrinsic_size() -> u32 { - Rococo::max_extrinsic_size() - } - - fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { - // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = messages_target::maximal_incoming_message_dispatch_weight( - Rococo::max_extrinsic_weight(), - ); - - // we're charging for payload bytes in `With(Wococo | Rococo)MessageBridge::transaction_payment` function - // - // this bridge may be used to deliver all kind of messages, so we're not making any assumptions about - // minimal dispatch weight here - - 0..=upper_limit - } - - fn estimate_delivery_transaction( - message_payload: &[u8], - include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: Weight, - ) -> MessageTransaction { - let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); - let extra_bytes_in_payload = Weight::from(message_payload_len) - .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); - - MessageTransaction { - dispatch_weight: extra_bytes_in_payload - .saturating_mul(ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) - .saturating_add(DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) - .saturating_sub(if include_pay_dispatch_fee_cost { - 0 - } else { - PAY_INBOUND_DISPATCH_FEE_WEIGHT - }) - .saturating_add(message_dispatch_weight), - size: message_payload_len - .saturating_add(EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(TX_EXTRA_BYTES), - } - } - - fn transaction_payment(transaction: MessageTransaction) -> Balance { - // current fee multiplier is used here - bridge_runtime_common::messages::transaction_payment( - crate::BlockWeights::get() - .get(frame_support::weights::DispatchClass::Normal) - .base_extrinsic, - crate::TransactionByteFee::get(), - pallet_transaction_payment::Pallet::::next_fee_multiplier(), - |weight| WeightToFee::weight_to_fee(&weight), - transaction, - ) - } -} - -impl TargetHeaderChain, crate::AccountId> - for RococoLikeChain -where - B: MessageBridge, - B::ThisChain: ChainWithMessages, - B::BridgedChain: ChainWithMessages, - GI: 'static, - Runtime: pallet_bridge_grandpa::Config, - <>::BridgedChain as bp_runtime::Chain>::Hash: - From, -{ - type Error = &'static str; - type MessagesDeliveryProof = - messages_source::FromBridgedChainMessagesDeliveryProof; - - fn verify_message( - payload: &messages_source::FromThisChainMessagePayload, - ) -> Result<(), Self::Error> { - messages_source::verify_chain_message::(payload) - } - - fn verify_messages_delivery_proof( - proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages_source::verify_messages_delivery_proof::(proof) - } -} - -impl SourceHeaderChain for RococoLikeChain -where - B: MessageBridge, - B::BridgedChain: ChainWithMessages, - GI: 'static, - Runtime: pallet_bridge_grandpa::Config, - <>::BridgedChain as bp_runtime::Chain>::Hash: - From, -{ - type Error = &'static str; - type MessagesProof = messages_target::FromBridgedChainMessagesProof; - - fn verify_messages_proof( - proof: Self::MessagesProof, - messages_count: u32, - ) -> Result>, Self::Error> { - messages_target::verify_messages_proof::(proof, messages_count) - .and_then(verify_inbound_messages_lane) - } -} - -/// Error that happens when we are receiving incoming message via unexpected lane. -const INBOUND_LANE_DISABLED: &str = "The inbound message lane is disabled."; - -/// Verify that lanes of inbound messages are enabled. -fn verify_inbound_messages_lane( - messages: ProvedMessages>, -) -> Result>, &'static str> { - let allowed_incoming_lanes = [[0, 0, 0, 0]]; - if messages.keys().any(|lane_id| !allowed_incoming_lanes.contains(lane_id)) { - return Err(INBOUND_LANE_DISABLED) - } - Ok(messages) -} - -/// The cost of delivery confirmation transaction. -pub struct GetDeliveryConfirmationTransactionFee; - -impl Get for GetDeliveryConfirmationTransactionFee { - fn get() -> Balance { - ::transaction_payment( - RococoAtRococo::estimate_delivery_confirmation_transaction(), - ) - } -} - -impl SenderOrigin for crate::Origin { - fn linked_account(&self) -> Option { - match self.caller { - crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => - Some(submitter.clone()), - crate::OriginCaller::system(frame_system::RawOrigin::Root) | - crate::OriginCaller::system(frame_system::RawOrigin::None) => - crate::RootAccountForPayments::get(), - _ => None, - } - } -} - -/// This module contains definitions that are used by the messages pallet instance, "deployed" at Rococo. -mod at_rococo { - use super::*; - - /// Message bridge that is "deployed" at Rococo chain and connecting it to Wococo chain. - #[derive(RuntimeDebug, Clone, Copy)] - pub struct AtRococoWithWococoMessageBridge; - - impl MessageBridge for AtRococoWithWococoMessageBridge { - const THIS_CHAIN_ID: ChainId = ROCOCO_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = WOCOCO_CHAIN_ID; - const RELAYER_FEE_PERCENT: u32 = 10; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = - bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; - - type ThisChain = RococoAtRococo; - type BridgedChain = WococoAtRococo; - - fn bridged_balance_to_this_balance( - bridged_balance: bp_wococo::Balance, - _bridged_to_this_conversion_rate_override: Option, - ) -> bp_rococo::Balance { - bridged_balance - } - } - - /// Message payload for Rococo -> Wococo messages as it is seen at the Rococo. - pub type ToWococoMessagePayload = - messages_source::FromThisChainMessagePayload; - - /// Message verifier for Rococo -> Wococo messages at Rococo. - pub type ToWococoMessageVerifier = - messages_source::FromThisChainMessageVerifier; - - /// Message payload for Wococo -> Rococo messages as it is seen at Rococo. - pub type FromWococoMessagePayload = - messages_target::FromBridgedChainMessagePayload; - - /// Encoded Rococo Call as it comes from Wococo. - pub type FromWococoEncodedCall = - messages_target::FromBridgedChainEncodedMessageCall; - - /// Call-dispatch based message dispatch for Wococo -> Rococo messages. - pub type FromWococoMessageDispatch = messages_target::FromBridgedChainMessageDispatch< - AtRococoWithWococoMessageBridge, - Runtime, - Balances, - crate::AtRococoFromWococoMessagesDispatch, - >; -} - -/// This module contains definitions that are used by the messages pallet instance, "deployed" at Wococo. -mod at_wococo { - use super::*; - - /// Message bridge that is "deployed" at Wococo chain and connecting it to Rococo chain. - #[derive(RuntimeDebug, Clone, Copy)] - pub struct AtWococoWithRococoMessageBridge; - - impl MessageBridge for AtWococoWithRococoMessageBridge { - const THIS_CHAIN_ID: ChainId = WOCOCO_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = ROCOCO_CHAIN_ID; - const RELAYER_FEE_PERCENT: u32 = 10; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = - bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; - - type ThisChain = WococoAtWococo; - type BridgedChain = RococoAtWococo; - - fn bridged_balance_to_this_balance( - bridged_balance: bp_rococo::Balance, - _bridged_to_this_conversion_rate_override: Option, - ) -> bp_wococo::Balance { - bridged_balance - } - } - - /// Message payload for Wococo -> Rococo messages as it is seen at the Wococo. - pub type ToRococoMessagePayload = - messages_source::FromThisChainMessagePayload; - - /// Message verifier for Wococo -> Rococo messages at Wococo. - pub type ToRococoMessageVerifier = - messages_source::FromThisChainMessageVerifier; - - /// Message payload for Rococo -> Wococo messages as it is seen at Wococo. - pub type FromRococoMessagePayload = - messages_target::FromBridgedChainMessagePayload; - - /// Encoded Wococo Call as it comes from Rococo. - pub type FromRococoEncodedCall = - messages_target::FromBridgedChainEncodedMessageCall; - - /// Call-dispatch based message dispatch for Rococo -> Wococo messages. - pub type FromRococoMessageDispatch = messages_target::FromBridgedChainMessageDispatch< - AtWococoWithRococoMessageBridge, - Runtime, - Balances, - crate::AtWococoFromRococoMessagesDispatch, - >; -} - -#[cfg(test)] -mod tests { - use super::*; - use bp_messages::{target_chain::ProvedLaneMessages, MessageData, MessageKey}; - use bridge_runtime_common::messages; - use parity_scale_codec::{Decode, Encode}; - use sp_runtime::traits::TrailingZeroInput; - - #[test] - fn ensure_rococo_messages_weights_are_correct() { - // **NOTE**: the main purpose of this test is to be sure that any message that is sumbitted - // to (any) inbound lane in Rococo<>Wococo bridge can be delivered to the bridged chain. - // Since we deal with testnets here, in case of failure + urgency: - // - // 1) ping bridges team about this failure (see the CODEOWNERS file if you're unsure who to ping); - // 2) comment/#[ignore] the test. - - // we don't have any knowledge of messages-at-Rococo weights, so we'll be using - // weights of one of our testnets, which should be accurate enough - type Weights = pallet_bridge_messages::weights::MillauWeight; - - pallet_bridge_messages::ensure_weights_are_correct::( - DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, - ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, - MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - PAY_INBOUND_DISPATCH_FEE_WEIGHT, - crate::RocksDbWeight::get(), - ); - - let max_incoming_message_proof_size = bp_rococo::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(Rococo::max_extrinsic_size()), - ); - pallet_bridge_messages::ensure_able_to_receive_message::( - Rococo::max_extrinsic_size(), - Rococo::max_extrinsic_weight(), - max_incoming_message_proof_size, - messages::target::maximal_incoming_message_dispatch_weight( - Rococo::max_extrinsic_weight(), - ), - ); - - let max_incoming_inbound_lane_data_proof_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint( - bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, - bp_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, - ) - .unwrap_or(u32::MAX); - pallet_bridge_messages::ensure_able_to_receive_confirmation::( - Rococo::max_extrinsic_size(), - Rococo::max_extrinsic_weight(), - max_incoming_inbound_lane_data_proof_size, - bp_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - bp_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - crate::RocksDbWeight::get(), - ); - } - - #[test] - fn ensure_rococo_tx_extra_bytes_constant_is_correct() { - // **NOTE**: this test checks that we're computing transaction fee (for bridged chain, which, in - // case of Rococo<>Wococo, means any chain) on-chain properly. If this assert fails: - // - // 1) just fix the `TX_EXTRA_BYTES` constant to actual (or sightly rounded up) value; - // 2) (only if it has changed significantly (> x2 times)) ping the bridges team (see the CODEOWNERS - // file if you're unsure who to ping) - - let signed_extra: crate::SignedExtra = ( - frame_system::CheckNonZeroSender::new(), - frame_system::CheckSpecVersion::new(), - frame_system::CheckTxVersion::new(), - frame_system::CheckGenesis::new(), - frame_system::CheckMortality::from(sp_runtime::generic::Era::mortal( - u64::MAX, - u64::MAX, - )), - frame_system::CheckNonce::from(primitives::v2::Nonce::MAX), - frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from( - primitives::v2::Balance::MAX, - ), - ); - let mut zeroes = TrailingZeroInput::zeroes(); - let extra_bytes_in_transaction = signed_extra.encoded_size() + - crate::Address::decode(&mut zeroes).unwrap().encoded_size() + - crate::Signature::decode(&mut zeroes).unwrap().encoded_size(); - assert!( - TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, - "Hardcoded number of extra bytes in Rococo transaction {} is lower than actual value: {}", - TX_EXTRA_BYTES, - extra_bytes_in_transaction, - ); - } - - fn proved_messages(lane_id: LaneId) -> ProvedMessages> { - vec![( - lane_id, - ProvedLaneMessages { - lane_state: None, - messages: vec![Message { - key: MessageKey { lane_id, nonce: 0 }, - data: MessageData { payload: vec![], fee: 0 }, - }], - }, - )] - .into_iter() - .collect() - } - - #[test] - fn verify_inbound_messages_lane_succeeds() { - assert_eq!( - verify_inbound_messages_lane(proved_messages([0, 0, 0, 0])), - Ok(proved_messages([0, 0, 0, 0])), - ); - } - - #[test] - fn verify_inbound_messages_lane_fails() { - assert_eq!( - verify_inbound_messages_lane(proved_messages([0, 0, 0, 1])), - Err(INBOUND_LANE_DISABLED), - ); - - let proved_messages = proved_messages([0, 0, 0, 0]) - .into_iter() - .chain(proved_messages([0, 0, 0, 1])) - .collect(); - assert_eq!(verify_inbound_messages_lane(proved_messages), Err(INBOUND_LANE_DISABLED),); - } -} diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index cfd1567cda46..6100ae0c9fac 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -20,6 +20,7 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit = "256"] +use pallet_nis::WithMaximumOf; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use primitives::v2::{ AccountId, AccountIndex, Balance, BlockNumber, CandidateEvent, CandidateHash, @@ -55,7 +56,7 @@ use frame_support::{ construct_runtime, parameter_types, traits::{ Contains, EitherOfDiverse, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, - PrivilegeCmp, WithdrawReasons, + PrivilegeCmp, StorageMapShim, WithdrawReasons, }, weights::ConstantMultiplier, PalletId, RuntimeDebug, @@ -65,7 +66,7 @@ use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId}; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_session::historical as session_historical; use pallet_transaction_payment::{CurrencyAdapter, FeeDetails, RuntimeDispatchInfo}; -use sp_core::{OpaqueMetadata, H256}; +use sp_core::{ConstU128, OpaqueMetadata, H256}; use sp_mmr_primitives as mmr; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, @@ -108,14 +109,14 @@ 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: 9310, + spec_version: 9360, impl_version: 0, #[cfg(not(feature = "disable-runtime-api"))] apis: RUNTIME_API_VERSIONS, #[cfg(feature = "disable-runtime-api")] apis: sp_version::create_apis_vec![[]], - transaction_version: 15, - state_version: 0, + transaction_version: 17, + state_version: 1, }; /// The BABE epoch configuration at genesis. @@ -793,7 +794,7 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); - pub const MaxSignatories: u16 = 100; + pub const MaxSignatories: u32 = 100; } impl pallet_multisig::Config for Runtime { @@ -954,7 +955,7 @@ impl InstanceFilter for ProxyType { RuntimeCall::Scheduler(..) | RuntimeCall::Proxy(..) | RuntimeCall::Multisig(..) | - RuntimeCall::Gilt(..) | + RuntimeCall::Nis(..) | RuntimeCall::Registrar(paras_registrar::Call::register {..}) | RuntimeCall::Registrar(paras_registrar::Call::deregister {..}) | // Specifically omitting Registrar `swap` @@ -1186,33 +1187,57 @@ impl auctions::Config for Runtime { type WeightInfo = weights::runtime_common_auctions::WeightInfo; } +type NisCounterpartInstance = pallet_balances::Instance2; +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU128<10_000_000_000>; // One RTC cent + type AccountStore = StorageMapShim< + pallet_balances::Account, + frame_system::Provider, + AccountId, + pallet_balances::AccountData, + >; + type MaxLocks = ConstU32<4>; + type MaxReserves = ConstU32<4>; + type ReserveIdentifier = [u8; 8]; + type WeightInfo = weights::pallet_balances_nis_counterpart_balances::WeightInfo; +} + parameter_types! { pub IgnoredIssuance: Balance = Treasury::pot(); - pub const QueueCount: u32 = 300; - pub const MaxQueueLen: u32 = 1000; - pub const FifoQueueLen: u32 = 250; - pub const GiltPeriod: BlockNumber = 30 * DAYS; - pub const MinFreeze: Balance = 10_000 * CENTS; + pub const NisBasePeriod: BlockNumber = 30 * DAYS; + pub const MinBid: Balance = 100 * UNITS; + pub MinReceipt: Perquintill = Perquintill::from_rational(1u64, 10_000_000u64); pub const IntakePeriod: BlockNumber = 5 * MINUTES; - pub const MaxIntakeBids: u32 = 100; + pub MaxIntakeWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10; + pub const ThawThrottle: (Perquintill, BlockNumber) = (Perquintill::from_percent(25), 5); + pub storage NisTarget: Perquintill = Perquintill::zero(); + pub const NisPalletId: PalletId = PalletId(*b"py/nis "); } -impl pallet_gilt::Config for Runtime { +impl pallet_nis::Config for Runtime { + type WeightInfo = weights::pallet_nis::WeightInfo; type RuntimeEvent = RuntimeEvent; type Currency = Balances; type CurrencyBalance = Balance; - type AdminOrigin = MoreThanHalfCouncil; + type FundOrigin = frame_system::EnsureSigned; + type Counterpart = NisCounterpartBalances; + type CounterpartAmount = WithMaximumOf>; type Deficit = (); // Mint - type Surplus = (); // Burn type IgnoredIssuance = IgnoredIssuance; - type QueueCount = QueueCount; - type MaxQueueLen = MaxQueueLen; - type FifoQueueLen = FifoQueueLen; - type Period = GiltPeriod; - type MinFreeze = MinFreeze; + type Target = NisTarget; + type PalletId = NisPalletId; + type QueueCount = ConstU32<300>; + type MaxQueueLen = ConstU32<1000>; + type FifoQueueLen = ConstU32<250>; + type BasePeriod = NisBasePeriod; + type MinBid = MinBid; + type MinReceipt = MinReceipt; type IntakePeriod = IntakePeriod; - type MaxIntakeBids = MaxIntakeBids; - type WeightInfo = weights::pallet_gilt::WeightInfo; + type MaxIntakeWeight = MaxIntakeWeight; + type ThawThrottle = ThawThrottle; } impl pallet_beefy::Config for Runtime { @@ -1224,7 +1249,7 @@ impl pallet_beefy::Config for Runtime { type MmrHash = ::Output; impl pallet_mmr::Config for Runtime { - const INDEXING_PREFIX: &'static [u8] = b"mmr"; + const INDEXING_PREFIX: &'static [u8] = mmr::INDEXING_PREFIX; type Hashing = Keccak256; type Hash = MmrHash; type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest; @@ -1375,8 +1400,10 @@ construct_runtime! { // Tips module. Tips: pallet_tips::{Pallet, Call, Storage, Event} = 36, - // Gilts pallet. - Gilt: pallet_gilt::{Pallet, Call, Storage, Event, Config} = 38, + // NIS pallet. + Nis: pallet_nis::{Pallet, Call, Storage, Event} = 38, +// pub type NisCounterpartInstance = pallet_balances::Instance2; + NisCounterpartBalances: pallet_balances:: = 45, // Parachains pallets. Start indices at 50 to leave room. ParachainsOrigin: parachains_origin::{Pallet, Origin} = 50, @@ -1416,6 +1443,9 @@ construct_runtime! { // Validator Manager pallet. ValidatorManager: validator_manager::{Pallet, Call, Storage, Event} = 252, + // State trie migration pallet, only temporary. + StateTrieMigration: pallet_state_trie_migration = 254, + // Sudo. Sudo: pallet_sudo::{Pallet, Call, Storage, Event, Config} = 255, } @@ -1446,6 +1476,9 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + +pub type Migrations = (); + /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -1453,19 +1486,36 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - ( - // "Bound uses of call" - pallet_preimage::migration::v1::Migration, - pallet_scheduler::migration::v3::MigrateToV4, - pallet_democracy::migrations::v1::Migration, - pallet_multisig::migrations::v1::MigrateToV1, - // "Properly migrate weights to v2" - parachains_configuration::migration::v3::MigrateToV3, - ), + Migrations, >; /// The payload being signed in transactions. 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) + pub const MigrationSignedDepositPerItem: Balance = 1 * CENTS; + pub const MigrationSignedDepositBase: Balance = 20 * CENTS * 100; + pub const MigrationMaxKeyLen: u32 = 512; +} + +impl pallet_state_trie_migration::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type SignedDepositPerItem = MigrationSignedDepositPerItem; + type SignedDepositBase = MigrationSignedDepositBase; + type ControlOrigin = EnsureRoot; + // specific account for the migration, can trigger the signed migrations. + type SignedFilter = frame_system::EnsureSignedBy; + + // Use same weights as substrate ones. + type WeightInfo = pallet_state_trie_migration::weights::SubstrateWeight; + type MaxKeyLen = MigrationMaxKeyLen; +} + +frame_support::ord_parameter_types! { + pub const MigController: AccountId = AccountId::from(hex_literal::hex!("52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649")); +} + #[cfg(feature = "runtime-benchmarks")] #[macro_use] extern crate frame_benchmarking; @@ -1490,6 +1540,7 @@ mod benches { [runtime_parachains::ump, Ump] // Substrate [pallet_balances, Balances] + [pallet_balances, NisCounterpartBalances] [frame_benchmarking::baseline, Baseline::] [pallet_bounties, Bounties] [pallet_child_bounties, ChildBounties] @@ -1497,7 +1548,7 @@ mod benches { [pallet_collective, TechnicalCommittee] [pallet_democracy, Democracy] [pallet_elections_phragmen, PhragmenElection] - [pallet_gilt, Gilt] + [pallet_nis, Nis] [pallet_identity, Identity] [pallet_im_online, ImOnline] [pallet_indices, Indices] @@ -1691,52 +1742,19 @@ sp_api::impl_runtime_apis! { } impl mmr::MmrApi for Runtime { - fn generate_proof(block_number: BlockNumber) - -> Result<(mmr::EncodableOpaqueLeaf, mmr::Proof), mmr::Error> - { - Mmr::generate_batch_proof(vec![block_number]) - .and_then(|(leaves, proof)| Ok(( - mmr::EncodableOpaqueLeaf::from_leaf(&leaves[0]), - mmr::BatchProof::into_single_leaf_proof(proof)? - ))) - } - - fn verify_proof(leaf: mmr::EncodableOpaqueLeaf, proof: mmr::Proof) - -> Result<(), mmr::Error> - { - pub type MmrLeaf = <::LeafData as mmr::LeafDataProvider>::LeafData; - let leaf: MmrLeaf = leaf - .into_opaque_leaf() - .try_decode() - .ok_or(mmr::Error::Verify)?; - Mmr::verify_leaves(vec![leaf], mmr::Proof::into_batch_proof(proof)) - } - - fn verify_proof_stateless( - root: Hash, - leaf: mmr::EncodableOpaqueLeaf, - proof: mmr::Proof - ) -> Result<(), mmr::Error> { - let node = mmr::DataOrHash::Data(leaf.into_opaque_leaf()); - pallet_mmr::verify_leaves_proof::(root, vec![node], mmr::Proof::into_batch_proof(proof)) - } - fn mmr_root() -> Result { Ok(Mmr::mmr_root()) } - fn generate_batch_proof(block_numbers: Vec) - -> Result<(Vec, mmr::BatchProof), mmr::Error> - { - Mmr::generate_batch_proof(block_numbers) - .map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof)) + fn mmr_leaf_count() -> Result { + Ok(Mmr::mmr_leaves()) } - fn generate_historical_batch_proof( + fn generate_proof( block_numbers: Vec, - best_known_block_number: BlockNumber, - ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { - Mmr::generate_historical_batch_proof(block_numbers, best_known_block_number).map( + best_known_block_number: Option, + ) -> Result<(Vec, mmr::Proof), mmr::Error> { + Mmr::generate_proof(block_numbers, best_known_block_number).map( |(leaves, proof)| { ( leaves @@ -1749,7 +1767,7 @@ sp_api::impl_runtime_apis! { ) } - fn verify_batch_proof(leaves: Vec, proof: mmr::BatchProof) + fn verify_proof(leaves: Vec, proof: mmr::Proof) -> Result<(), mmr::Error> { pub type MmrLeaf = <::LeafData as mmr::LeafDataProvider>::LeafData; @@ -1760,10 +1778,10 @@ sp_api::impl_runtime_apis! { Mmr::verify_leaves(leaves, proof) } - fn verify_batch_proof_stateless( + fn verify_proof_stateless( root: Hash, leaves: Vec, - proof: mmr::BatchProof + proof: mmr::Proof ) -> Result<(), mmr::Error> { let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); pallet_mmr::verify_leaves_proof::(root, nodes, proof) diff --git a/runtime/rococo/src/weights/frame_benchmarking_baseline.rs b/runtime/rococo/src/weights/frame_benchmarking_baseline.rs index cc96e30d7401..31f2ca75f591 100644 --- a/runtime/rococo/src/weights/frame_benchmarking_baseline.rs +++ b/runtime/rococo/src/weights/frame_benchmarking_baseline.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_benchmarking::baseline` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -46,52 +46,54 @@ pub struct WeightInfo(PhantomData); impl frame_benchmarking::baseline::WeightInfo for WeightInfo { /// The range of component `i` is `[0, 1000000]`. fn addition(_i: u32, ) -> Weight { - // Minimum execution time: 100 nanoseconds. - Weight::from_ref_time(147_688 as u64) + // Minimum execution time: 108 nanoseconds. + Weight::from_ref_time(121_479) } /// The range of component `i` is `[0, 1000000]`. fn subtraction(_i: u32, ) -> Weight { - // Minimum execution time: 100 nanoseconds. - Weight::from_ref_time(147_383 as u64) + // Minimum execution time: 117 nanoseconds. + Weight::from_ref_time(210_102) } /// The range of component `i` is `[0, 1000000]`. fn multiplication(_i: u32, ) -> Weight { - // Minimum execution time: 90 nanoseconds. - Weight::from_ref_time(147_362 as u64) + // Minimum execution time: 109 nanoseconds. + Weight::from_ref_time(128_603) } /// The range of component `i` is `[0, 1000000]`. fn division(_i: u32, ) -> Weight { - // Minimum execution time: 94 nanoseconds. - Weight::from_ref_time(142_468 as u64) + // Minimum execution time: 108 nanoseconds. + Weight::from_ref_time(123_815) } /// The range of component `i` is `[0, 100]`. - fn hashing(_i: u32, ) -> Weight { - // Minimum execution time: 19_076_234 nanoseconds. - Weight::from_ref_time(19_306_096_061 as u64) + fn hashing(i: u32, ) -> Weight { + // Minimum execution time: 20_366_715 nanoseconds. + Weight::from_ref_time(20_558_729_024) + // Standard Error: 191_692 + .saturating_add(Weight::from_ref_time(1_124_523).saturating_mul(i.into())) } /// The range of component `i` is `[0, 100]`. fn sr25519_verification(i: u32, ) -> Weight { - // Minimum execution time: 152 nanoseconds. - Weight::from_ref_time(170_000 as u64) - // Standard Error: 22_217 - .saturating_add(Weight::from_ref_time(47_861_042 as u64).saturating_mul(i as u64)) + // Minimum execution time: 132 nanoseconds. + Weight::from_ref_time(193_000) + // Standard Error: 18_227 + .saturating_add(Weight::from_ref_time(47_399_966).saturating_mul(i.into())) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn storage_read(i: u32, ) -> Weight { - // Minimum execution time: 130 nanoseconds. - Weight::from_ref_time(143_000 as u64) - // Standard Error: 3_691 - .saturating_add(Weight::from_ref_time(1_837_360 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 120 nanoseconds. + Weight::from_ref_time(124_000) + // Standard Error: 4_672 + .saturating_add(Weight::from_ref_time(1_966_212).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn storage_write(i: u32, ) -> Weight { - // Minimum execution time: 104 nanoseconds. - Weight::from_ref_time(124_000 as u64) - // Standard Error: 857 - .saturating_add(Weight::from_ref_time(315_739 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 125 nanoseconds. + Weight::from_ref_time(132_000) + // Standard Error: 861 + .saturating_add(Weight::from_ref_time(335_750).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } } diff --git a/runtime/rococo/src/weights/frame_system.rs b/runtime/rococo/src/weights/frame_system.rs index f69a95d86eb1..7f36c0d2300f 100644 --- a/runtime/rococo/src/weights/frame_system.rs +++ b/runtime/rococo/src/weights/frame_system.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_system` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -46,51 +46,51 @@ pub struct WeightInfo(PhantomData); impl frame_system::WeightInfo for WeightInfo { /// The range of component `b` is `[0, 3932160]`. fn remark(b: u32, ) -> Weight { - // Minimum execution time: 3_577 nanoseconds. - Weight::from_ref_time(3_668_000 as u64) + // Minimum execution time: 3_972 nanoseconds. + Weight::from_ref_time(1_046_371) // Standard Error: 0 - .saturating_add(Weight::from_ref_time(413 as u64).saturating_mul(b as u64)) + .saturating_add(Weight::from_ref_time(414).saturating_mul(b.into())) } /// The range of component `b` is `[0, 3932160]`. fn remark_with_event(b: u32, ) -> Weight { - // Minimum execution time: 12_303 nanoseconds. - Weight::from_ref_time(12_411_000 as u64) + // Minimum execution time: 12_202 nanoseconds. + Weight::from_ref_time(12_397_000) // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_728 as u64).saturating_mul(b as u64)) + .saturating_add(Weight::from_ref_time(1_771).saturating_mul(b.into())) } // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - // Minimum execution time: 7_559 nanoseconds. - Weight::from_ref_time(7_837_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 8_086 nanoseconds. + Weight::from_ref_time(8_345_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { - // Minimum execution time: 3_705 nanoseconds. - Weight::from_ref_time(3_820_000 as u64) - // Standard Error: 2_019 - .saturating_add(Weight::from_ref_time(604_466 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 3_891 nanoseconds. + Weight::from_ref_time(3_984_000) + // Standard Error: 2_058 + .saturating_add(Weight::from_ref_time(626_682).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { - // Minimum execution time: 3_749 nanoseconds. - Weight::from_ref_time(3_791_000 as u64) - // Standard Error: 994 - .saturating_add(Weight::from_ref_time(433_769 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 3_961 nanoseconds. + Weight::from_ref_time(4_055_000) + // Standard Error: 918 + .saturating_add(Weight::from_ref_time(446_433).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { - // Minimum execution time: 5_101 nanoseconds. - Weight::from_ref_time(5_266_000 as u64) - // Standard Error: 1_406 - .saturating_add(Weight::from_ref_time(941_250 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 5_698 nanoseconds. + Weight::from_ref_time(5_831_000) + // Standard Error: 1_373 + .saturating_add(Weight::from_ref_time(971_252).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } } diff --git a/runtime/rococo/src/weights/mod.rs b/runtime/rococo/src/weights/mod.rs index 712783bc3e6c..f1657f95aa19 100644 --- a/runtime/rococo/src/weights/mod.rs +++ b/runtime/rococo/src/weights/mod.rs @@ -17,18 +17,19 @@ pub mod frame_system; pub mod pallet_balances; +pub mod pallet_balances_nis_counterpart_balances; pub mod pallet_bounties; pub mod pallet_child_bounties; pub mod pallet_collective_council; pub mod pallet_collective_technical_committee; pub mod pallet_democracy; pub mod pallet_elections_phragmen; -pub mod pallet_gilt; pub mod pallet_identity; pub mod pallet_im_online; pub mod pallet_indices; pub mod pallet_membership; pub mod pallet_multisig; +pub mod pallet_nis; pub mod pallet_preimage; pub mod pallet_proxy; pub mod pallet_scheduler; diff --git a/runtime/rococo/src/weights/pallet_balances.rs b/runtime/rococo/src/weights/pallet_balances.rs index 6bd0bcedd863..9e6af9772680 100644 --- a/runtime/rococo/src/weights/pallet_balances.rs +++ b/runtime/rococo/src/weights/pallet_balances.rs @@ -16,8 +16,8 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! DATE: 2022-11-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bm6`, 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: @@ -46,50 +46,50 @@ pub struct WeightInfo(PhantomData); impl pallet_balances::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - // Minimum execution time: 39_712 nanoseconds. - Weight::from_ref_time(40_827_000 as u64) + // Minimum execution time: 40_106 nanoseconds. + Weight::from_ref_time(40_750_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - // Minimum execution time: 30_010 nanoseconds. - Weight::from_ref_time(30_621_000 as u64) + // Minimum execution time: 30_737 nanoseconds. + Weight::from_ref_time(31_295_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - // Minimum execution time: 22_644 nanoseconds. - Weight::from_ref_time(23_092_000 as u64) + // Minimum execution time: 23_902 nanoseconds. + Weight::from_ref_time(24_338_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - // Minimum execution time: 25_591 nanoseconds. - Weight::from_ref_time(26_035_000 as u64) + // Minimum execution time: 26_492 nanoseconds. + Weight::from_ref_time(26_866_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:2 w:2) fn force_transfer() -> Weight { - // Minimum execution time: 39_942 nanoseconds. - Weight::from_ref_time(40_712_000 as u64) + // Minimum execution time: 40_384 nanoseconds. + Weight::from_ref_time(41_000_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - // Minimum execution time: 34_653 nanoseconds. - Weight::from_ref_time(35_543_000 as u64) + // Minimum execution time: 35_115 nanoseconds. + Weight::from_ref_time(35_696_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - // Minimum execution time: 19_879 nanoseconds. - Weight::from_ref_time(20_242_000 as u64) + // Minimum execution time: 20_274 nanoseconds. + Weight::from_ref_time(20_885_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } diff --git a/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs b/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs new file mode 100644 index 000000000000..0e914a1d1a69 --- /dev/null +++ b/runtime/rococo/src/weights/pallet_balances_nis_counterpart_balances.rs @@ -0,0 +1,105 @@ +// Copyright 2017-2022 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_balances` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! 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 +// benchmark +// pallet +// --chain=rococo-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_balances +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_balances`. +pub struct WeightInfo(PhantomData); +impl pallet_balances::WeightInfo for WeightInfo { + // Storage: NisCounterpartBalances Account (r:2 w:2) + // Storage: System Account (r:1 w:1) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + fn transfer() -> Weight { + // Minimum execution time: 45_274 nanoseconds. + Weight::from_ref_time(46_391_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + // Storage: NisCounterpartBalances Account (r:2 w:2) + // Storage: System Account (r:1 w:1) + fn transfer_keep_alive() -> Weight { + // Minimum execution time: 31_960 nanoseconds. + Weight::from_ref_time(32_954_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + // Storage: NisCounterpartBalances Account (r:1 w:1) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + fn set_balance_creating() -> Weight { + // Minimum execution time: 21_467 nanoseconds. + Weight::from_ref_time(22_401_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: NisCounterpartBalances Account (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + fn set_balance_killing() -> Weight { + // Minimum execution time: 30_013 nanoseconds. + Weight::from_ref_time(31_045_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + // Storage: NisCounterpartBalances Account (r:2 w:2) + // Storage: System Account (r:2 w:2) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + fn force_transfer() -> Weight { + // Minimum execution time: 43_705 nanoseconds. + Weight::from_ref_time(44_612_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } + // Storage: NisCounterpartBalances Account (r:2 w:2) + // Storage: System Account (r:1 w:1) + fn transfer_all() -> Weight { + // Minimum execution time: 40_854 nanoseconds. + Weight::from_ref_time(42_010_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + // Storage: NisCounterpartBalances Account (r:1 w:1) + fn force_unreserve() -> Weight { + // Minimum execution time: 20_620 nanoseconds. + Weight::from_ref_time(21_028_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/runtime/rococo/src/weights/pallet_bounties.rs b/runtime/rococo/src/weights/pallet_bounties.rs index 37e297782917..c0453039034c 100644 --- a/runtime/rococo/src/weights/pallet_bounties.rs +++ b/runtime/rococo/src/weights/pallet_bounties.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_bounties` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -50,101 +50,59 @@ impl pallet_bounties::WeightInfo for WeightInfo { // Storage: Bounties Bounties (r:0 w:1) /// The range of component `d` is `[0, 16384]`. fn propose_bounty(d: u32, ) -> Weight { - // Minimum execution time: 27_804 nanoseconds. - Weight::from_ref_time(29_056_744 as u64) + // Minimum execution time: 29_657 nanoseconds. + Weight::from_ref_time(31_673_110) // Standard Error: 5 - .saturating_add(Weight::from_ref_time(853 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + .saturating_add(Weight::from_ref_time(834).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) - // Storage: Bounties BountyApprovals (r:1 w:1) fn approve_bounty() -> Weight { - // Minimum execution time: 11_910 nanoseconds. - Weight::from_ref_time(12_122_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) fn propose_curator() -> Weight { - // Minimum execution time: 11_663 nanoseconds. - Weight::from_ref_time(11_833_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - // Minimum execution time: 38_804 nanoseconds. - Weight::from_ref_time(40_115_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - // Minimum execution time: 27_497 nanoseconds. - Weight::from_ref_time(27_869_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: ChildBounties ParentChildBounties (r:1 w:0) fn award_bounty() -> Weight { - // Minimum execution time: 23_864 nanoseconds. - Weight::from_ref_time(24_073_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: System Account (r:3 w:3) - // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - // Storage: Bounties BountyDescriptions (r:0 w:1) fn claim_bounty() -> Weight { - // Minimum execution time: 67_991 nanoseconds. - Weight::from_ref_time(68_966_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } // Storage: Bounties Bounties (r:1 w:1) // Storage: ChildBounties ParentChildBounties (r:1 w:0) // Storage: System Account (r:1 w:1) // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_proposed() -> Weight { - // Minimum execution time: 42_844 nanoseconds. - Weight::from_ref_time(43_685_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 47_373 nanoseconds. + Weight::from_ref_time(48_026_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } - // Storage: Bounties Bounties (r:1 w:1) - // Storage: ChildBounties ParentChildBounties (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: Bounties BountyDescriptions (r:0 w:1) fn close_bounty_active() -> Weight { - // Minimum execution time: 51_853 nanoseconds. - Weight::from_ref_time(52_609_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:1) fn extend_bounty_expiry() -> Weight { - // Minimum execution time: 20_967 nanoseconds. - Weight::from_ref_time(21_226_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } // Storage: Bounties BountyApprovals (r:1 w:1) - // Storage: Bounties Bounties (r:2 w:2) - // Storage: System Account (r:4 w:4) /// The range of component `b` is `[0, 100]`. - fn spend_funds(b: u32, ) -> Weight { - // Minimum execution time: 6_700 nanoseconds. - Weight::from_ref_time(12_393_217 as u64) - // Standard Error: 25_027 - .saturating_add(Weight::from_ref_time(25_035_038 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(b as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(b as u64))) + fn spend_funds(_b: u32, ) -> Weight { + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(3_372_484) } } diff --git a/runtime/rococo/src/weights/pallet_child_bounties.rs b/runtime/rococo/src/weights/pallet_child_bounties.rs index f811ffcd32c1..f54ac22c98bf 100644 --- a/runtime/rococo/src/weights/pallet_child_bounties.rs +++ b/runtime/rococo/src/weights/pallet_child_bounties.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_child_bounties` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -44,88 +44,37 @@ use sp_std::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) - // Storage: Bounties Bounties (r:1 w:0) - // Storage: System Account (r:2 w:2) - // Storage: ChildBounties ChildBountyCount (r:1 w:1) - // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) - // Storage: ChildBounties ChildBounties (r:0 w:1) /// The range of component `d` is `[0, 16384]`. - fn add_child_bounty(d: u32, ) -> Weight { - // Minimum execution time: 49_807 nanoseconds. - Weight::from_ref_time(50_899_264 as u64) - // Standard Error: 12 - .saturating_add(Weight::from_ref_time(927 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + fn add_child_bounty(_d: u32, ) -> Weight { + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) fn propose_curator() -> Weight { - // Minimum execution time: 19_942 nanoseconds. - Weight::from_ref_time(20_503_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: System Account (r:1 w:1) fn accept_curator() -> Weight { - // Minimum execution time: 35_241 nanoseconds. - Weight::from_ref_time(35_682_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: Bounties Bounties (r:1 w:0) - // Storage: System Account (r:1 w:1) fn unassign_curator() -> Weight { - // Minimum execution time: 47_679 nanoseconds. - Weight::from_ref_time(48_686_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) fn award_child_bounty() -> Weight { - // Minimum execution time: 26_401 nanoseconds. - Weight::from_ref_time(27_254_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: System Account (r:3 w:3) - // Storage: ChildBounties ParentChildBounties (r:1 w:1) - // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn claim_child_bounty() -> Weight { - // Minimum execution time: 67_126 nanoseconds. - Weight::from_ref_time(67_652_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - // Storage: ChildBounties ParentChildBounties (r:1 w:1) - // Storage: System Account (r:2 w:2) - // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_added() -> Weight { - // Minimum execution time: 49_894 nanoseconds. - Weight::from_ref_time(50_434_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } - // Storage: Bounties Bounties (r:1 w:0) - // Storage: ChildBounties ChildBounties (r:1 w:1) - // Storage: System Account (r:3 w:3) - // Storage: ChildBounties ChildrenCuratorFees (r:1 w:1) - // Storage: ChildBounties ParentChildBounties (r:1 w:1) - // Storage: ChildBounties ChildBountyDescriptions (r:0 w:1) fn close_child_bounty_active() -> Weight { - // Minimum execution time: 59_485 nanoseconds. - Weight::from_ref_time(59_939_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 0 nanoseconds. + Weight::from_ref_time(0) } } diff --git a/runtime/rococo/src/weights/pallet_collective_council.rs b/runtime/rococo/src/weights/pallet_collective_council.rs index b50a114c5446..9b27cbc4471b 100644 --- a/runtime/rococo/src/weights/pallet_collective_council.rs +++ b/runtime/rococo/src/weights/pallet_collective_council.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -55,80 +55,80 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 17_198 nanoseconds. - Weight::from_ref_time(17_384_000 as u64) - // Standard Error: 42_549 - .saturating_add(Weight::from_ref_time(4_789_978 as u64).saturating_mul(m as u64)) - // Standard Error: 42_549 - .saturating_add(Weight::from_ref_time(6_897_746 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 18_113 nanoseconds. + Weight::from_ref_time(18_345_000) + // Standard Error: 44_428 + .saturating_add(Weight::from_ref_time(5_019_922).saturating_mul(m.into())) + // Standard Error: 44_428 + .saturating_add(Weight::from_ref_time(7_234_332).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } // Storage: Council Members (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 19_159 nanoseconds. - Weight::from_ref_time(18_873_138 as u64) - // Standard Error: 20 - .saturating_add(Weight::from_ref_time(1_734 as u64).saturating_mul(b as u64)) - // Standard Error: 209 - .saturating_add(Weight::from_ref_time(13_414 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 20_515 nanoseconds. + Weight::from_ref_time(20_113_963) + // Standard Error: 36 + .saturating_add(Weight::from_ref_time(2_039).saturating_mul(b.into())) + // Standard Error: 377 + .saturating_add(Weight::from_ref_time(12_442).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 21_451 nanoseconds. - Weight::from_ref_time(20_640_157 as u64) - // Standard Error: 24 - .saturating_add(Weight::from_ref_time(1_781 as u64).saturating_mul(b as u64)) - // Standard Error: 251 - .saturating_add(Weight::from_ref_time(23_485 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) + // Minimum execution time: 23_139 nanoseconds. + Weight::from_ref_time(22_040_575) + // Standard Error: 43 + .saturating_add(Weight::from_ref_time(2_014).saturating_mul(b.into())) + // Standard Error: 447 + .saturating_add(Weight::from_ref_time(20_546).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) } // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) // Storage: Council ProposalCount (r:1 w:1) // Storage: Council Voting (r:0 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 27_077 nanoseconds. - Weight::from_ref_time(27_154_776 as u64) - // Standard Error: 69 - .saturating_add(Weight::from_ref_time(3_336 as u64).saturating_mul(b as u64)) - // Standard Error: 727 - .saturating_add(Weight::from_ref_time(22_804 as u64).saturating_mul(m as u64)) - // Standard Error: 718 - .saturating_add(Weight::from_ref_time(108_762 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 28_499 nanoseconds. + Weight::from_ref_time(29_820_960) + // Standard Error: 68 + .saturating_add(Weight::from_ref_time(2_874).saturating_mul(b.into())) + // Standard Error: 714 + .saturating_add(Weight::from_ref_time(20_234).saturating_mul(m.into())) + // Standard Error: 705 + .saturating_add(Weight::from_ref_time(112_423).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Council Members (r:1 w:0) // Storage: Council Voting (r:1 w:1) /// The range of component `m` is `[5, 100]`. /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { - // Minimum execution time: 26_405 nanoseconds. - Weight::from_ref_time(27_242_136 as u64) - // Standard Error: 283 - .saturating_add(Weight::from_ref_time(39_794 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_401 nanoseconds. + Weight::from_ref_time(30_711_957) + // Standard Error: 558 + .saturating_add(Weight::from_ref_time(38_689).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) @@ -139,36 +139,36 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 29_536 nanoseconds. - Weight::from_ref_time(31_574_900 as u64) - // Standard Error: 542 - .saturating_add(Weight::from_ref_time(23_451 as u64).saturating_mul(m as u64)) - // Standard Error: 529 - .saturating_add(Weight::from_ref_time(85_053 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 31_116 nanoseconds. + Weight::from_ref_time(33_590_647) + // Standard Error: 507 + .saturating_add(Weight::from_ref_time(17_735).saturating_mul(m.into())) + // Standard Error: 494 + .saturating_add(Weight::from_ref_time(97_606).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 40_231 nanoseconds. - Weight::from_ref_time(40_496_273 as u64) - // Standard Error: 66 - .saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(b as u64)) - // Standard Error: 698 - .saturating_add(Weight::from_ref_time(22_943 as u64).saturating_mul(m as u64)) - // Standard Error: 681 - .saturating_add(Weight::from_ref_time(98_812 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 41_266 nanoseconds. + Weight::from_ref_time(42_416_248) + // Standard Error: 62 + .saturating_add(Weight::from_ref_time(2_225).saturating_mul(b.into())) + // Standard Error: 661 + .saturating_add(Weight::from_ref_time(15_161).saturating_mul(m.into())) + // Standard Error: 644 + .saturating_add(Weight::from_ref_time(116_981).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) @@ -180,37 +180,37 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { - // Minimum execution time: 32_640 nanoseconds. - Weight::from_ref_time(33_861_599 as u64) - // Standard Error: 460 - .saturating_add(Weight::from_ref_time(25_138 as u64).saturating_mul(m as u64)) - // Standard Error: 448 - .saturating_add(Weight::from_ref_time(83_121 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 34_391 nanoseconds. + Weight::from_ref_time(35_671_180) + // Standard Error: 455 + .saturating_add(Weight::from_ref_time(23_178).saturating_mul(m.into())) + // Standard Error: 444 + .saturating_add(Weight::from_ref_time(96_114).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Voting (r:1 w:1) // Storage: Council Members (r:1 w:0) // Storage: Council Prime (r:1 w:0) // Storage: Council ProposalOf (r:1 w:1) // Storage: Council Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 42_282 nanoseconds. - Weight::from_ref_time(42_777_378 as u64) - // Standard Error: 56 - .saturating_add(Weight::from_ref_time(1_586 as u64).saturating_mul(b as u64)) - // Standard Error: 600 - .saturating_add(Weight::from_ref_time(27_257 as u64).saturating_mul(m as u64)) - // Standard Error: 585 - .saturating_add(Weight::from_ref_time(97_813 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 43_531 nanoseconds. + Weight::from_ref_time(45_311_272) + // Standard Error: 86 + .saturating_add(Weight::from_ref_time(2_224).saturating_mul(b.into())) + // Standard Error: 910 + .saturating_add(Weight::from_ref_time(7_970).saturating_mul(m.into())) + // Standard Error: 887 + .saturating_add(Weight::from_ref_time(118_368).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Council Proposals (r:1 w:1) // Storage: Council Voting (r:0 w:1) @@ -218,11 +218,11 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `p` is `[1, 100]`. /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { - // Minimum execution time: 17_821 nanoseconds. - Weight::from_ref_time(21_443_640 as u64) - // Standard Error: 815 - .saturating_add(Weight::from_ref_time(96_451 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 19_674 nanoseconds. + Weight::from_ref_time(23_018_532) + // Standard Error: 767 + .saturating_add(Weight::from_ref_time(102_556).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/rococo/src/weights/pallet_collective_technical_committee.rs b/runtime/rococo/src/weights/pallet_collective_technical_committee.rs index 97f0f5b650f5..67ef57379f50 100644 --- a/runtime/rococo/src/weights/pallet_collective_technical_committee.rs +++ b/runtime/rococo/src/weights/pallet_collective_technical_committee.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_collective` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -55,80 +55,80 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 17_528 nanoseconds. - Weight::from_ref_time(17_901_000 as u64) - // Standard Error: 43_125 - .saturating_add(Weight::from_ref_time(4_810_355 as u64).saturating_mul(m as u64)) - // Standard Error: 43_125 - .saturating_add(Weight::from_ref_time(7_024_302 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 18_296 nanoseconds. + Weight::from_ref_time(18_626_000) + // Standard Error: 45_137 + .saturating_add(Weight::from_ref_time(5_133_683).saturating_mul(m.into())) + // Standard Error: 45_137 + .saturating_add(Weight::from_ref_time(7_349_526).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(p.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } // Storage: TechnicalCommittee Members (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 19_706 nanoseconds. - Weight::from_ref_time(19_036_289 as u64) - // Standard Error: 20 - .saturating_add(Weight::from_ref_time(1_775 as u64).saturating_mul(b as u64)) - // Standard Error: 206 - .saturating_add(Weight::from_ref_time(14_332 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 20_975 nanoseconds. + Weight::from_ref_time(20_296_697) + // Standard Error: 36 + .saturating_add(Weight::from_ref_time(1_955).saturating_mul(b.into())) + // Standard Error: 380 + .saturating_add(Weight::from_ref_time(12_823).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:0) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[1, 100]`. fn propose_execute(b: u32, m: u32, ) -> Weight { - // Minimum execution time: 21_770 nanoseconds. - Weight::from_ref_time(21_071_371 as u64) - // Standard Error: 20 - .saturating_add(Weight::from_ref_time(1_882 as u64).saturating_mul(b as u64)) - // Standard Error: 207 - .saturating_add(Weight::from_ref_time(22_530 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) + // Minimum execution time: 23_422 nanoseconds. + Weight::from_ref_time(22_146_912) + // Standard Error: 42 + .saturating_add(Weight::from_ref_time(1_970).saturating_mul(b.into())) + // Standard Error: 438 + .saturating_add(Weight::from_ref_time(21_239).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) } // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:1) // Storage: TechnicalCommittee ProposalCount (r:1 w:1) // Storage: TechnicalCommittee Voting (r:0 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[2, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 27_900 nanoseconds. - Weight::from_ref_time(28_420_350 as u64) - // Standard Error: 65 - .saturating_add(Weight::from_ref_time(3_419 as u64).saturating_mul(b as u64)) - // Standard Error: 680 - .saturating_add(Weight::from_ref_time(19_077 as u64).saturating_mul(m as u64)) - // Standard Error: 671 - .saturating_add(Weight::from_ref_time(114_674 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 29_001 nanoseconds. + Weight::from_ref_time(30_369_164) + // Standard Error: 66 + .saturating_add(Weight::from_ref_time(3_373).saturating_mul(b.into())) + // Standard Error: 696 + .saturating_add(Weight::from_ref_time(17_814).saturating_mul(m.into())) + // Standard Error: 687 + .saturating_add(Weight::from_ref_time(119_793).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee Voting (r:1 w:1) /// The range of component `m` is `[5, 100]`. /// The range of component `m` is `[5, 100]`. fn vote(m: u32, ) -> Weight { - // Minimum execution time: 27_932 nanoseconds. - Weight::from_ref_time(28_884_621 as u64) - // Standard Error: 327 - .saturating_add(Weight::from_ref_time(40_552 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_990 nanoseconds. + Weight::from_ref_time(31_263_891) + // Standard Error: 484 + .saturating_add(Weight::from_ref_time(39_455).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) @@ -139,36 +139,36 @@ impl pallet_collective::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 30_909 nanoseconds. - Weight::from_ref_time(32_299_057 as u64) - // Standard Error: 468 - .saturating_add(Weight::from_ref_time(23_986 as u64).saturating_mul(m as u64)) - // Standard Error: 456 - .saturating_add(Weight::from_ref_time(85_238 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 32_528 nanoseconds. + Weight::from_ref_time(33_990_709) + // Standard Error: 445 + .saturating_add(Weight::from_ref_time(20_655).saturating_mul(m.into())) + // Standard Error: 434 + .saturating_add(Weight::from_ref_time(98_367).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 41_125 nanoseconds. - Weight::from_ref_time(41_496_038 as u64) - // Standard Error: 85 - .saturating_add(Weight::from_ref_time(1_920 as u64).saturating_mul(b as u64)) - // Standard Error: 900 - .saturating_add(Weight::from_ref_time(20_485 as u64).saturating_mul(m as u64)) - // Standard Error: 877 - .saturating_add(Weight::from_ref_time(99_758 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 42_010 nanoseconds. + Weight::from_ref_time(43_128_498) + // Standard Error: 58 + .saturating_add(Weight::from_ref_time(2_045).saturating_mul(b.into())) + // Standard Error: 618 + .saturating_add(Weight::from_ref_time(16_423).saturating_mul(m.into())) + // Standard Error: 603 + .saturating_add(Weight::from_ref_time(117_415).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) @@ -180,37 +180,37 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. fn close_disapproved(m: u32, p: u32, ) -> Weight { - // Minimum execution time: 33_319 nanoseconds. - Weight::from_ref_time(34_385_990 as u64) - // Standard Error: 452 - .saturating_add(Weight::from_ref_time(27_482 as u64).saturating_mul(m as u64)) - // Standard Error: 441 - .saturating_add(Weight::from_ref_time(84_077 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 34_919 nanoseconds. + Weight::from_ref_time(36_142_161) + // Standard Error: 465 + .saturating_add(Weight::from_ref_time(24_375).saturating_mul(m.into())) + // Standard Error: 453 + .saturating_add(Weight::from_ref_time(97_836).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Voting (r:1 w:1) // Storage: TechnicalCommittee Members (r:1 w:0) // Storage: TechnicalCommittee Prime (r:1 w:0) // Storage: TechnicalCommittee ProposalOf (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:1) - /// The range of component `b` is `[1, 1024]`. + /// The range of component `b` is `[2, 1024]`. /// The range of component `m` is `[4, 100]`. /// The range of component `p` is `[1, 100]`. - /// The range of component `b` is `[1, 1024]`. + /// 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 { - // Minimum execution time: 42_399 nanoseconds. - Weight::from_ref_time(43_752_937 as u64) - // Standard Error: 57 - .saturating_add(Weight::from_ref_time(1_548 as u64).saturating_mul(b as u64)) - // Standard Error: 604 - .saturating_add(Weight::from_ref_time(25_138 as u64).saturating_mul(m as u64)) - // Standard Error: 589 - .saturating_add(Weight::from_ref_time(97_514 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 44_517 nanoseconds. + Weight::from_ref_time(45_699_139) + // Standard Error: 71 + .saturating_add(Weight::from_ref_time(2_183).saturating_mul(b.into())) + // Standard Error: 750 + .saturating_add(Weight::from_ref_time(12_186).saturating_mul(m.into())) + // Standard Error: 731 + .saturating_add(Weight::from_ref_time(119_123).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalCommittee Proposals (r:1 w:1) // Storage: TechnicalCommittee Voting (r:0 w:1) @@ -218,11 +218,11 @@ impl pallet_collective::WeightInfo for WeightInfo { /// The range of component `p` is `[1, 100]`. /// The range of component `p` is `[1, 100]`. fn disapprove_proposal(p: u32, ) -> Weight { - // Minimum execution time: 18_277 nanoseconds. - Weight::from_ref_time(21_867_405 as u64) - // Standard Error: 758 - .saturating_add(Weight::from_ref_time(98_872 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 20_155 nanoseconds. + Weight::from_ref_time(23_331_853) + // Standard Error: 708 + .saturating_add(Weight::from_ref_time(105_166).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/rococo/src/weights/pallet_democracy.rs b/runtime/rococo/src/weights/pallet_democracy.rs index 6f48824dbaf7..7af6a2586d26 100644 --- a/runtime/rococo/src/weights/pallet_democracy.rs +++ b/runtime/rococo/src/weights/pallet_democracy.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_democracy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -49,43 +49,43 @@ impl pallet_democracy::WeightInfo for WeightInfo { // Storage: Democracy Blacklist (r:1 w:0) // Storage: Democracy DepositOf (r:0 w:1) fn propose() -> Weight { - // Minimum execution time: 41_755 nanoseconds. - Weight::from_ref_time(43_134_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 45_102 nanoseconds. + Weight::from_ref_time(46_100_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy DepositOf (r:1 w:1) fn second() -> Weight { - // Minimum execution time: 39_573 nanoseconds. - Weight::from_ref_time(40_193_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 42_173 nanoseconds. + Weight::from_ref_time(43_692_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_new() -> Weight { - // Minimum execution time: 49_316 nanoseconds. - Weight::from_ref_time(49_938_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 52_656 nanoseconds. + Weight::from_ref_time(53_732_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn vote_existing() -> Weight { - // Minimum execution time: 49_518 nanoseconds. - Weight::from_ref_time(49_900_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 52_725 nanoseconds. + Weight::from_ref_time(53_241_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Cancellations (r:1 w:1) fn emergency_cancel() -> Weight { - // Minimum execution time: 21_261 nanoseconds. - Weight::from_ref_time(21_511_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 22_228 nanoseconds. + Weight::from_ref_time(22_952_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy PublicProps (r:1 w:1) // Storage: Democracy DepositOf (r:1 w:1) @@ -94,75 +94,75 @@ impl pallet_democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy Blacklist (r:0 w:1) fn blacklist() -> Weight { - // Minimum execution time: 76_503 nanoseconds. - Weight::from_ref_time(77_929_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 82_061 nanoseconds. + Weight::from_ref_time(83_519_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:0) fn external_propose() -> Weight { - // Minimum execution time: 15_863 nanoseconds. - Weight::from_ref_time(16_354_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 17_824 nanoseconds. + Weight::from_ref_time(18_278_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_majority() -> Weight { - // Minimum execution time: 5_089 nanoseconds. - Weight::from_ref_time(5_254_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_362 nanoseconds. + Weight::from_ref_time(5_542_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:0 w:1) fn external_propose_default() -> Weight { - // Minimum execution time: 5_069 nanoseconds. - Weight::from_ref_time(5_209_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_350 nanoseconds. + Weight::from_ref_time(5_616_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn fast_track() -> Weight { - // Minimum execution time: 20_253 nanoseconds. - Weight::from_ref_time(20_515_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 21_582 nanoseconds. + Weight::from_ref_time(21_928_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy NextExternal (r:1 w:1) // Storage: Democracy Blacklist (r:1 w:1) fn veto_external() -> Weight { - // Minimum execution time: 26_095 nanoseconds. - Weight::from_ref_time(26_879_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 27_966 nanoseconds. + Weight::from_ref_time(28_300_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy PublicProps (r:1 w:1) // Storage: Democracy DepositOf (r:1 w:1) // Storage: System Account (r:1 w:1) fn cancel_proposal() -> Weight { - // Minimum execution time: 64_771 nanoseconds. - Weight::from_ref_time(66_324_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 69_747 nanoseconds. + Weight::from_ref_time(70_803_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:0 w:1) fn cancel_referendum() -> Weight { - // Minimum execution time: 13_645 nanoseconds. - Weight::from_ref_time(14_111_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 14_208 nanoseconds. + Weight::from_ref_time(14_786_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) // Storage: Democracy ReferendumInfoOf (r:2 w:0) /// The range of component `r` is `[0, 99]`. fn on_initialize_base(r: u32, ) -> Weight { - // Minimum execution time: 6_099 nanoseconds. - Weight::from_ref_time(9_326_206 as u64) - // Standard Error: 3_862 - .saturating_add(Weight::from_ref_time(2_099_699 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 6_447 nanoseconds. + Weight::from_ref_time(9_495_812) + // Standard Error: 4_275 + .saturating_add(Weight::from_ref_time(2_150_879).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy LowestUnbaked (r:1 w:1) // Storage: Democracy ReferendumCount (r:1 w:0) @@ -172,91 +172,91 @@ impl pallet_democracy::WeightInfo for WeightInfo { // Storage: Democracy ReferendumInfoOf (r:2 w:0) /// The range of component `r` is `[0, 99]`. fn on_initialize_base_with_launch_period(r: u32, ) -> Weight { - // Minimum execution time: 8_538 nanoseconds. - Weight::from_ref_time(12_081_949 as u64) - // Standard Error: 4_231 - .saturating_add(Weight::from_ref_time(2_092_594 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_728 nanoseconds. + Weight::from_ref_time(12_024_568) + // Standard Error: 5_204 + .saturating_add(Weight::from_ref_time(2_158_987).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy VotingOf (r:3 w:3) // Storage: Balances Locks (r:1 w:1) // Storage: Democracy ReferendumInfoOf (r:2 w:2) /// The range of component `r` is `[0, 99]`. fn delegate(r: u32, ) -> Weight { - // Minimum execution time: 40_763 nanoseconds. - Weight::from_ref_time(47_624_671 as u64) - // Standard Error: 5_958 - .saturating_add(Weight::from_ref_time(3_011_398 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64))) + // Minimum execution time: 43_730 nanoseconds. + Weight::from_ref_time(50_825_189) + // Standard Error: 5_823 + .saturating_add(Weight::from_ref_time(3_149_863).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((1_u64).saturating_mul(r.into()))) } // Storage: Democracy VotingOf (r:2 w:2) // Storage: Democracy ReferendumInfoOf (r:2 w:2) /// The range of component `r` is `[0, 99]`. fn undelegate(r: u32, ) -> Weight { - // Minimum execution time: 24_439 nanoseconds. - Weight::from_ref_time(26_378_140 as u64) - // Standard Error: 9_158 - .saturating_add(Weight::from_ref_time(3_034_925 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64))) + // Minimum execution time: 26_463 nanoseconds. + Weight::from_ref_time(29_431_700) + // Standard Error: 5_066 + .saturating_add(Weight::from_ref_time(3_107_920).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(r.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(r.into()))) } // Storage: Democracy PublicProps (r:0 w:1) fn clear_public_proposals() -> Weight { - // Minimum execution time: 5_702 nanoseconds. - Weight::from_ref_time(5_854_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_893 nanoseconds. + Weight::from_ref_time(6_106_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) /// The range of component `r` is `[0, 99]`. fn unlock_remove(r: u32, ) -> Weight { - // Minimum execution time: 23_168 nanoseconds. - Weight::from_ref_time(30_468_516 as u64) - // Standard Error: 1_663 - .saturating_add(Weight::from_ref_time(33_327 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 25_613 nanoseconds. + Weight::from_ref_time(33_093_793) + // Standard Error: 1_669 + .saturating_add(Weight::from_ref_time(33_084).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy VotingOf (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) /// The range of component `r` is `[0, 99]`. fn unlock_set(r: u32, ) -> Weight { - // Minimum execution time: 28_828 nanoseconds. - Weight::from_ref_time(30_266_125 as u64) - // Standard Error: 700 - .saturating_add(Weight::from_ref_time(71_389 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 31_597 nanoseconds. + Weight::from_ref_time(32_687_724) + // Standard Error: 636 + .saturating_add(Weight::from_ref_time(75_534).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) /// The range of component `r` is `[1, 100]`. fn remove_vote(r: u32, ) -> Weight { - // Minimum execution time: 15_780 nanoseconds. - Weight::from_ref_time(18_485_254 as u64) - // Standard Error: 890 - .saturating_add(Weight::from_ref_time(73_643 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 17_420 nanoseconds. + Weight::from_ref_time(19_826_791) + // Standard Error: 876 + .saturating_add(Weight::from_ref_time(76_078).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Democracy ReferendumInfoOf (r:1 w:1) // Storage: Democracy VotingOf (r:1 w:1) /// The range of component `r` is `[1, 100]`. fn remove_other_vote(r: u32, ) -> Weight { - // Minimum execution time: 15_661 nanoseconds. - Weight::from_ref_time(18_442_344 as u64) - // Standard Error: 957 - .saturating_add(Weight::from_ref_time(75_374 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 17_285 nanoseconds. + Weight::from_ref_time(19_747_323) + // Standard Error: 941 + .saturating_add(Weight::from_ref_time(77_698).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/rococo/src/weights/pallet_elections_phragmen.rs b/runtime/rococo/src/weights/pallet_elections_phragmen.rs index 8aaf623a9abd..6472acacb811 100644 --- a/runtime/rococo/src/weights/pallet_elections_phragmen.rs +++ b/runtime/rococo/src/weights/pallet_elections_phragmen.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_elections_phragmen` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -50,13 +50,11 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: PhragmenElection Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) /// The range of component `v` is `[1, 16]`. - fn vote_equal(v: u32, ) -> Weight { - // Minimum execution time: 30_460 nanoseconds. - Weight::from_ref_time(34_092_598 as u64) - // Standard Error: 15_458 - .saturating_add(Weight::from_ref_time(9_646 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + fn vote_equal(_v: u32, ) -> Weight { + // Minimum execution time: 32_371 nanoseconds. + Weight::from_ref_time(36_279_856) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Candidates (r:1 w:0) // Storage: PhragmenElection Members (r:1 w:0) @@ -65,12 +63,12 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Balances Locks (r:1 w:1) /// The range of component `v` is `[2, 16]`. fn vote_more(v: u32, ) -> Weight { - // Minimum execution time: 40_039 nanoseconds. - Weight::from_ref_time(42_074_863 as u64) - // Standard Error: 4_200 - .saturating_add(Weight::from_ref_time(149_127 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 43_151 nanoseconds. + Weight::from_ref_time(44_063_579) + // Standard Error: 5_084 + .saturating_add(Weight::from_ref_time(130_645).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Candidates (r:1 w:0) // Storage: PhragmenElection Members (r:1 w:0) @@ -79,42 +77,42 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Balances Locks (r:1 w:1) /// The range of component `v` is `[2, 16]`. fn vote_less(v: u32, ) -> Weight { - // Minimum execution time: 39_892 nanoseconds. - Weight::from_ref_time(41_863_175 as u64) - // Standard Error: 7_944 - .saturating_add(Weight::from_ref_time(191_849 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 42_148 nanoseconds. + Weight::from_ref_time(43_777_573) + // Standard Error: 6_625 + .saturating_add(Weight::from_ref_time(160_293).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Voting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) fn remove_voter() -> Weight { - // Minimum execution time: 38_954 nanoseconds. - Weight::from_ref_time(39_459_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 41_190 nanoseconds. + Weight::from_ref_time(41_621_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Candidates (r:1 w:1) // Storage: PhragmenElection Members (r:1 w:0) // Storage: PhragmenElection RunnersUp (r:1 w:0) /// The range of component `c` is `[1, 1000]`. fn submit_candidacy(c: u32, ) -> Weight { - // Minimum execution time: 36_293 nanoseconds. - Weight::from_ref_time(27_988_157 as u64) - // Standard Error: 969 - .saturating_add(Weight::from_ref_time(94_416 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 37_427 nanoseconds. + Weight::from_ref_time(29_293_841) + // Standard Error: 1_053 + .saturating_add(Weight::from_ref_time(97_420).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: PhragmenElection Candidates (r:1 w:1) /// The range of component `c` is `[1, 1000]`. fn renounce_candidacy_candidate(c: u32, ) -> Weight { - // Minimum execution time: 31_731 nanoseconds. - Weight::from_ref_time(23_893_126 as u64) - // Standard Error: 976 - .saturating_add(Weight::from_ref_time(68_105 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 33_012 nanoseconds. + Weight::from_ref_time(24_872_179) + // Standard Error: 1_044 + .saturating_add(Weight::from_ref_time(72_609).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: PhragmenElection Members (r:1 w:1) // Storage: PhragmenElection RunnersUp (r:1 w:1) @@ -122,22 +120,22 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn renounce_candidacy_members() -> Weight { - // Minimum execution time: 44_666 nanoseconds. - Weight::from_ref_time(45_740_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 46_468 nanoseconds. + Weight::from_ref_time(47_505_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: PhragmenElection RunnersUp (r:1 w:1) fn renounce_candidacy_runners_up() -> Weight { - // Minimum execution time: 34_151 nanoseconds. - Weight::from_ref_time(34_813_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 35_632 nanoseconds. + Weight::from_ref_time(36_854_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Benchmark Override (r:0 w:0) fn remove_member_without_replacement() -> Weight { // Minimum execution time: 2_000_000_000 nanoseconds. - Weight::from_ref_time(2_000_000_000_000 as u64) + Weight::from_ref_time(2_000_000_000_000) } // Storage: PhragmenElection Members (r:1 w:1) // Storage: System Account (r:1 w:1) @@ -146,10 +144,10 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn // Storage: Council Proposals (r:1 w:0) // Storage: Council Members (r:0 w:1) fn remove_member_with_replacement() -> Weight { - // Minimum execution time: 59_230 nanoseconds. - Weight::from_ref_time(60_055_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 60_998 nanoseconds. + Weight::from_ref_time(62_539_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: PhragmenElection Voting (r:5001 w:5000) // Storage: PhragmenElection Members (r:1 w:0) @@ -160,13 +158,13 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn /// The range of component `v` is `[5000, 10000]`. /// The range of component `d` is `[0, 5000]`. fn clean_defunct_voters(v: u32, _d: u32, ) -> Weight { - // Minimum execution time: 278_626_833 nanoseconds. - Weight::from_ref_time(279_736_954_000 as u64) - // Standard Error: 239_547 - .saturating_add(Weight::from_ref_time(34_254_809 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(v as u64))) + // Minimum execution time: 285_403_894 nanoseconds. + Weight::from_ref_time(285_860_459_000) + // Standard Error: 248_756 + .saturating_add(Weight::from_ref_time(35_708_872).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) } // Storage: PhragmenElection Candidates (r:1 w:1) // Storage: PhragmenElection Members (r:1 w:1) @@ -181,16 +179,16 @@ impl pallet_elections_phragmen::WeightInfo for WeightIn /// The range of component `v` is `[1, 10000]`. /// The range of component `e` is `[10000, 160000]`. fn election_phragmen(c: u32, v: u32, e: u32, ) -> Weight { - // Minimum execution time: 28_441_420 nanoseconds. - Weight::from_ref_time(28_674_262_000 as u64) - // Standard Error: 546_104 - .saturating_add(Weight::from_ref_time(45_370_047 as u64).saturating_mul(v as u64)) - // Standard Error: 35_045 - .saturating_add(Weight::from_ref_time(2_344_981 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(265 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().writes(6 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + // Minimum execution time: 29_683_290 nanoseconds. + Weight::from_ref_time(29_810_601_000) + // Standard Error: 548_695 + .saturating_add(Weight::from_ref_time(46_375_520).saturating_mul(v.into())) + // Standard Error: 35_211 + .saturating_add(Weight::from_ref_time(2_381_861).saturating_mul(e.into())) + .saturating_add(T::DbWeight::get().reads(265)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(c.into()))) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes(6)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(c.into()))) } } diff --git a/runtime/rococo/src/weights/pallet_gilt.rs b/runtime/rococo/src/weights/pallet_gilt.rs deleted file mode 100644 index d49582396034..000000000000 --- a/runtime/rococo/src/weights/pallet_gilt.rs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2017-2022 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_gilt` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! 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 -// benchmark -// pallet -// --chain=rococo-dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_gilt -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/rococo/src/weights/ - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::Weight}; -use sp_std::marker::PhantomData; - -/// Weight functions for `pallet_gilt`. -pub struct WeightInfo(PhantomData); -impl pallet_gilt::WeightInfo for WeightInfo { - // Storage: Gilt Queues (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - /// The range of component `l` is `[0, 999]`. - fn place_bid(l: u32, ) -> Weight { - // Minimum execution time: 37_199 nanoseconds. - Weight::from_ref_time(34_701_639 as u64) - // Standard Error: 698 - .saturating_add(Weight::from_ref_time(80_025 as u64).saturating_mul(l as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Gilt Queues (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - fn place_bid_max() -> Weight { - // Minimum execution time: 103_025 nanoseconds. - Weight::from_ref_time(104_609_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Gilt Queues (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - /// The range of component `l` is `[1, 1000]`. - fn retract_bid(l: u32, ) -> Weight { - // Minimum execution time: 38_232 nanoseconds. - Weight::from_ref_time(35_611_328 as u64) - // Standard Error: 682 - .saturating_add(Weight::from_ref_time(61_944 as u64).saturating_mul(l as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Gilt ActiveTotal (r:1 w:1) - fn set_target() -> Weight { - // Minimum execution time: 6_921 nanoseconds. - Weight::from_ref_time(7_130_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: Gilt Active (r:1 w:1) - // Storage: Gilt ActiveTotal (r:1 w:1) - fn thaw() -> Weight { - // Minimum execution time: 46_291 nanoseconds. - Weight::from_ref_time(46_762_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: Gilt ActiveTotal (r:1 w:0) - fn pursue_target_noop() -> Weight { - // Minimum execution time: 3_116 nanoseconds. - Weight::from_ref_time(3_268_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - } - // Storage: Gilt ActiveTotal (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - // Storage: Gilt Queues (r:1 w:1) - // Storage: Gilt Active (r:0 w:20) - /// The range of component `b` is `[0, 1000]`. - fn pursue_target_per_item(b: u32, ) -> Weight { - // Minimum execution time: 28_468 nanoseconds. - Weight::from_ref_time(29_472_202 as u64) - // Standard Error: 3_145 - .saturating_add(Weight::from_ref_time(4_024_451 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(b as u64))) - } - // Storage: Gilt ActiveTotal (r:1 w:1) - // Storage: Gilt QueueTotals (r:1 w:1) - // Storage: Gilt Queues (r:6 w:6) - // Storage: Gilt Active (r:0 w:6) - /// The range of component `q` is `[0, 300]`. - fn pursue_target_per_queue(q: u32, ) -> Weight { - // Minimum execution time: 28_371 nanoseconds. - Weight::from_ref_time(26_392_395 as u64) - // Standard Error: 7_213 - .saturating_add(Weight::from_ref_time(6_686_202 as u64).saturating_mul(q as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(q as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(q as u64))) - } -} diff --git a/runtime/rococo/src/weights/pallet_identity.rs b/runtime/rococo/src/weights/pallet_identity.rs index 70ebeb3504ed..17a411e09668 100644 --- a/runtime/rococo/src/weights/pallet_identity.rs +++ b/runtime/rococo/src/weights/pallet_identity.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_identity` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -47,52 +47,52 @@ impl pallet_identity::WeightInfo for WeightInfo { // Storage: Identity Registrars (r:1 w:1) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { - // Minimum execution time: 16_642 nanoseconds. - Weight::from_ref_time(18_035_521 as u64) - // Standard Error: 3_625 - .saturating_add(Weight::from_ref_time(148_827 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 17_581 nanoseconds. + Weight::from_ref_time(19_890_660) + // Standard Error: 8_046 + .saturating_add(Weight::from_ref_time(132_069).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) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn set_identity(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 34_747 nanoseconds. - Weight::from_ref_time(34_532_655 as u64) - // Standard Error: 3_411 - .saturating_add(Weight::from_ref_time(80_073 as u64).saturating_mul(r as u64)) - // Standard Error: 665 - .saturating_add(Weight::from_ref_time(308_527 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 37_972 nanoseconds. + Weight::from_ref_time(37_428_271) + // Standard Error: 4_326 + .saturating_add(Weight::from_ref_time(84_736).saturating_mul(r.into())) + // Standard Error: 844 + .saturating_add(Weight::from_ref_time(359_416).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:2 w:2) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { - // Minimum execution time: 9_852 nanoseconds. - Weight::from_ref_time(27_573_957 as u64) - // Standard Error: 4_818 - .saturating_add(Weight::from_ref_time(2_092_485 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 11_434 nanoseconds. + Weight::from_ref_time(30_956_114) + // Standard Error: 5_671 + .saturating_add(Weight::from_ref_time(2_281_000).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()))) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:2) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { - // Minimum execution time: 9_954 nanoseconds. - Weight::from_ref_time(27_765_722 as u64) - // Standard Error: 4_213 - .saturating_add(Weight::from_ref_time(905_843 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 11_486 nanoseconds. + Weight::from_ref_time(30_108_725) + // Standard Error: 4_786 + .saturating_add(Weight::from_ref_time(1_002_668).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) // Storage: Identity IdentityOf (r:1 w:1) @@ -101,88 +101,88 @@ impl pallet_identity::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. /// The range of component `x` is `[0, 100]`. fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - // Minimum execution time: 49_507 nanoseconds. - Weight::from_ref_time(35_702_864 as u64) - // Standard Error: 6_439 - .saturating_add(Weight::from_ref_time(84_332 as u64).saturating_mul(r as u64)) - // Standard Error: 1_257 - .saturating_add(Weight::from_ref_time(871_228 as u64).saturating_mul(s as u64)) - // Standard Error: 1_257 - .saturating_add(Weight::from_ref_time(161_551 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 54_704 nanoseconds. + Weight::from_ref_time(40_527_327) + // Standard Error: 5_343 + .saturating_add(Weight::from_ref_time(11_312).saturating_mul(r.into())) + // Standard Error: 1_043 + .saturating_add(Weight::from_ref_time(946_143).saturating_mul(s.into())) + // Standard Error: 1_043 + .saturating_add(Weight::from_ref_time(179_728).saturating_mul(x.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) // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn request_judgement(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 37_215 nanoseconds. - Weight::from_ref_time(35_730_521 as u64) - // Standard Error: 4_756 - .saturating_add(Weight::from_ref_time(142_311 as u64).saturating_mul(r as u64)) - // Standard Error: 928 - .saturating_add(Weight::from_ref_time(329_605 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 39_551 nanoseconds. + Weight::from_ref_time(37_659_487) + // Standard Error: 4_624 + .saturating_add(Weight::from_ref_time(128_213).saturating_mul(r.into())) + // Standard Error: 902 + .saturating_add(Weight::from_ref_time(389_168).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn cancel_request(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 34_136 nanoseconds. - Weight::from_ref_time(32_639_742 as u64) - // Standard Error: 3_750 - .saturating_add(Weight::from_ref_time(99_769 as u64).saturating_mul(r as u64)) - // Standard Error: 731 - .saturating_add(Weight::from_ref_time(325_990 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 36_041 nanoseconds. + Weight::from_ref_time(36_214_401) + // Standard Error: 3_914 + .saturating_add(Weight::from_ref_time(38_342).saturating_mul(r.into())) + // Standard Error: 763 + .saturating_add(Weight::from_ref_time(377_992).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity Registrars (r:1 w:1) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { - // Minimum execution time: 8_676 nanoseconds. - Weight::from_ref_time(9_604_692 as u64) - // Standard Error: 2_429 - .saturating_add(Weight::from_ref_time(143_010 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_144 nanoseconds. + Weight::from_ref_time(10_854_119) + // Standard Error: 1_971 + .saturating_add(Weight::from_ref_time(142_648).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) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { - // Minimum execution time: 9_001 nanoseconds. - Weight::from_ref_time(9_939_836 as u64) - // Standard Error: 2_336 - .saturating_add(Weight::from_ref_time(124_249 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_128 nanoseconds. + Weight::from_ref_time(11_440_965) + // Standard Error: 3_587 + .saturating_add(Weight::from_ref_time(101_559).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) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { - // Minimum execution time: 8_532 nanoseconds. - Weight::from_ref_time(9_666_826 as u64) - // Standard Error: 2_421 - .saturating_add(Weight::from_ref_time(132_033 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_953 nanoseconds. + Weight::from_ref_time(10_934_038) + // Standard Error: 2_412 + .saturating_add(Weight::from_ref_time(132_052).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) // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 19]`. /// The range of component `x` is `[0, 100]`. fn provide_judgement(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 27_590 nanoseconds. - Weight::from_ref_time(27_728_670 as u64) - // Standard Error: 6_540 - .saturating_add(Weight::from_ref_time(64_407 as u64).saturating_mul(r as u64)) - // Standard Error: 1_210 - .saturating_add(Weight::from_ref_time(555_394 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_702 nanoseconds. + Weight::from_ref_time(30_298_846) + // Standard Error: 5_501 + .saturating_add(Weight::from_ref_time(58_613).saturating_mul(r.into())) + // Standard Error: 1_017 + .saturating_add(Weight::from_ref_time(636_435).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity IdentityOf (r:1 w:1) @@ -192,62 +192,62 @@ impl pallet_identity::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. /// The range of component `x` is `[0, 100]`. fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight { - // Minimum execution time: 61_955 nanoseconds. - Weight::from_ref_time(46_510_774 as u64) - // Standard Error: 4_608 - .saturating_add(Weight::from_ref_time(86_445 as u64).saturating_mul(r as u64)) - // Standard Error: 899 - .saturating_add(Weight::from_ref_time(881_362 as u64).saturating_mul(s as u64)) - // Standard Error: 899 - .saturating_add(Weight::from_ref_time(163_552 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 67_284 nanoseconds. + Weight::from_ref_time(50_824_327) + // Standard Error: 4_969 + .saturating_add(Weight::from_ref_time(92_429).saturating_mul(r.into())) + // Standard Error: 970 + .saturating_add(Weight::from_ref_time(955_284).saturating_mul(s.into())) + // Standard Error: 970 + .saturating_add(Weight::from_ref_time(180_077).saturating_mul(x.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) // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { - // Minimum execution time: 30_847 nanoseconds. - Weight::from_ref_time(36_838_521 as u64) - // Standard Error: 1_693 - .saturating_add(Weight::from_ref_time(76_909 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 33_868 nanoseconds. + Weight::from_ref_time(39_975_173) + // Standard Error: 1_674 + .saturating_add(Weight::from_ref_time(82_318).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) // Storage: Identity SuperOf (r:1 w:1) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { - // Minimum execution time: 13_510 nanoseconds. - Weight::from_ref_time(15_952_774 as u64) - // Standard Error: 770 - .saturating_add(Weight::from_ref_time(28_646 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_257 nanoseconds. + Weight::from_ref_time(18_187_947) + // Standard Error: 1_023 + .saturating_add(Weight::from_ref_time(26_257).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) // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { - // Minimum execution time: 34_391 nanoseconds. - Weight::from_ref_time(38_454_498 as u64) - // Standard Error: 1_269 - .saturating_add(Weight::from_ref_time(63_899 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 37_982 nanoseconds. + Weight::from_ref_time(42_035_528) + // Standard Error: 1_448 + .saturating_add(Weight::from_ref_time(62_243).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) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { - // Minimum execution time: 24_290 nanoseconds. - Weight::from_ref_time(28_022_763 as u64) - // Standard Error: 1_224 - .saturating_add(Weight::from_ref_time(66_833 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 26_843 nanoseconds. + Weight::from_ref_time(30_988_644) + // Standard Error: 2_122 + .saturating_add(Weight::from_ref_time(65_305).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/rococo/src/weights/pallet_im_online.rs b/runtime/rococo/src/weights/pallet_im_online.rs index a74b39b76898..73ca83deed21 100644 --- a/runtime/rococo/src/weights/pallet_im_online.rs +++ b/runtime/rococo/src/weights/pallet_im_online.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_im_online` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -53,13 +53,13 @@ impl pallet_im_online::WeightInfo for WeightInfo { /// The range of component `k` is `[1, 1000]`. /// The range of component `e` is `[1, 100]`. fn validate_unsigned_and_then_heartbeat(k: u32, e: u32, ) -> Weight { - // Minimum execution time: 95_841 nanoseconds. - Weight::from_ref_time(77_009_555 as u64) - // Standard Error: 346 - .saturating_add(Weight::from_ref_time(24_371 as u64).saturating_mul(k as u64)) - // Standard Error: 3_490 - .saturating_add(Weight::from_ref_time(315_554 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 99_004 nanoseconds. + Weight::from_ref_time(78_439_877) + // Standard Error: 317 + .saturating_add(Weight::from_ref_time(26_717).saturating_mul(k.into())) + // Standard Error: 3_195 + .saturating_add(Weight::from_ref_time(335_732).saturating_mul(e.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/rococo/src/weights/pallet_indices.rs b/runtime/rococo/src/weights/pallet_indices.rs index 34aba445dc17..0240362a3ece 100644 --- a/runtime/rococo/src/weights/pallet_indices.rs +++ b/runtime/rococo/src/weights/pallet_indices.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_indices` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -46,39 +46,39 @@ pub struct WeightInfo(PhantomData); impl pallet_indices::WeightInfo for WeightInfo { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - // Minimum execution time: 25_145 nanoseconds. - Weight::from_ref_time(25_606_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_751 nanoseconds. + Weight::from_ref_time(27_231_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - // Minimum execution time: 30_827 nanoseconds. - Weight::from_ref_time(31_599_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 34_082 nanoseconds. + Weight::from_ref_time(34_626_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - // Minimum execution time: 25_537 nanoseconds. - Weight::from_ref_time(26_081_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 28_172 nanoseconds. + Weight::from_ref_time(28_514_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - // Minimum execution time: 26_069 nanoseconds. - Weight::from_ref_time(26_540_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 28_352 nanoseconds. + Weight::from_ref_time(28_863_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - // Minimum execution time: 31_344 nanoseconds. - Weight::from_ref_time(31_825_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 33_221 nanoseconds. + Weight::from_ref_time(34_119_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/rococo/src/weights/pallet_membership.rs b/runtime/rococo/src/weights/pallet_membership.rs index e890a40f28c0..8bfbcdceee08 100644 --- a/runtime/rococo/src/weights/pallet_membership.rs +++ b/runtime/rococo/src/weights/pallet_membership.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_membership` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -50,12 +50,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 99]`. fn add_member(m: u32, ) -> Weight { - // Minimum execution time: 20_314 nanoseconds. - Weight::from_ref_time(20_916_793 as u64) - // Standard Error: 390 - .saturating_add(Weight::from_ref_time(41_741 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 21_136 nanoseconds. + Weight::from_ref_time(22_199_184) + // Standard Error: 775 + .saturating_add(Weight::from_ref_time(37_798).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -64,12 +64,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[2, 100]`. fn remove_member(m: u32, ) -> Weight { - // Minimum execution time: 23_137 nanoseconds. - Weight::from_ref_time(23_518_466 as u64) - // Standard Error: 465 - .saturating_add(Weight::from_ref_time(36_105 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 23_685 nanoseconds. + Weight::from_ref_time(24_466_367) + // Standard Error: 472 + .saturating_add(Weight::from_ref_time(34_991).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -78,12 +78,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[2, 100]`. fn swap_member(m: u32, ) -> Weight { - // Minimum execution time: 22_933 nanoseconds. - Weight::from_ref_time(23_505_635 as u64) - // Standard Error: 555 - .saturating_add(Weight::from_ref_time(47_816 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 23_333 nanoseconds. + Weight::from_ref_time(24_424_170) + // Standard Error: 560 + .saturating_add(Weight::from_ref_time(51_782).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -92,12 +92,12 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn reset_member(m: u32, ) -> Weight { - // Minimum execution time: 22_168 nanoseconds. - Weight::from_ref_time(23_311_086 as u64) - // Standard Error: 1_186 - .saturating_add(Weight::from_ref_time(163_040 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 23_020 nanoseconds. + Weight::from_ref_time(24_181_199) + // Standard Error: 704 + .saturating_add(Weight::from_ref_time(167_335).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: TechnicalMembership Members (r:1 w:1) // Storage: TechnicalCommittee Proposals (r:1 w:0) @@ -106,33 +106,33 @@ impl pallet_membership::WeightInfo for WeightInfo { // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn change_key(m: u32, ) -> Weight { - // Minimum execution time: 22_971 nanoseconds. - Weight::from_ref_time(24_067_443 as u64) - // Standard Error: 566 - .saturating_add(Weight::from_ref_time(49_410 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 24_297 nanoseconds. + Weight::from_ref_time(25_086_241) + // Standard Error: 538 + .saturating_add(Weight::from_ref_time(50_159).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: TechnicalMembership Members (r:1 w:0) // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn set_prime(m: u32, ) -> Weight { - // Minimum execution time: 8_505 nanoseconds. - Weight::from_ref_time(8_976_375 as u64) - // Standard Error: 220 - .saturating_add(Weight::from_ref_time(10_869 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 8_962 nanoseconds. + Weight::from_ref_time(9_315_767) + // Standard Error: 206 + .saturating_add(Weight::from_ref_time(10_404).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: TechnicalMembership Prime (r:0 w:1) // Storage: TechnicalCommittee Prime (r:0 w:1) /// The range of component `m` is `[1, 100]`. fn clear_prime(m: u32, ) -> Weight { - // Minimum execution time: 5_032 nanoseconds. - Weight::from_ref_time(5_347_858 as u64) - // Standard Error: 156 - .saturating_add(Weight::from_ref_time(647 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 5_438 nanoseconds. + Weight::from_ref_time(5_757_911) + // Standard Error: 157 + .saturating_add(Weight::from_ref_time(605).saturating_mul(m.into())) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/rococo/src/weights/pallet_multisig.rs b/runtime/rococo/src/weights/pallet_multisig.rs index 300e4704ef8d..dae6c75886b4 100644 --- a/runtime/rococo/src/weights/pallet_multisig.rs +++ b/runtime/rococo/src/weights/pallet_multisig.rs @@ -16,8 +16,8 @@ //! Autogenerated weights for `pallet_multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-26, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bm2`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! 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: @@ -28,11 +28,11 @@ // --steps=50 // --repeat=20 // --pallet=pallet_multisig -// --extrinsic= +// --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --header=./file_header.txt -// --output=runtime/rococo/src/weights/ +// --output=./runtime/rococo/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -46,81 +46,81 @@ pub struct WeightInfo(PhantomData); impl pallet_multisig::WeightInfo for WeightInfo { /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { - // Minimum execution time: 14_582 nanoseconds. - Weight::from_ref_time(15_014_888 as u64) + // Minimum execution time: 15_772 nanoseconds. + Weight::from_ref_time(16_255_218) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(490 as u64).saturating_mul(z as u64)) + .saturating_add(Weight::from_ref_time(597).saturating_mul(z.into())) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) /// 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 { - // Minimum execution time: 41_651 nanoseconds. - Weight::from_ref_time(34_224_425 as u64) - // Standard Error: 735 - .saturating_add(Weight::from_ref_time(80_357 as u64).saturating_mul(s as u64)) - // Standard Error: 7 - .saturating_add(Weight::from_ref_time(1_489 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 45_441 nanoseconds. + Weight::from_ref_time(37_064_110) + // Standard Error: 910 + .saturating_add(Weight::from_ref_time(95_519).saturating_mul(s.into())) + // Standard Error: 8 + .saturating_add(Weight::from_ref_time(1_540).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Multisig Multisigs (r:1 w:1) /// 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 { - // Minimum execution time: 31_520 nanoseconds. - Weight::from_ref_time(24_283_932 as u64) - // Standard Error: 615 - .saturating_add(Weight::from_ref_time(80_034 as u64).saturating_mul(s as u64)) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(1_490 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 35_187 nanoseconds. + Weight::from_ref_time(27_053_340) + // Standard Error: 605 + .saturating_add(Weight::from_ref_time(88_646).saturating_mul(s.into())) + // Standard Error: 5 + .saturating_add(Weight::from_ref_time(1_551).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) // Storage: System Account (r:1 w:1) /// 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 { - // Minimum execution time: 44_639 nanoseconds. - Weight::from_ref_time(35_788_014 as u64) - // Standard Error: 655 - .saturating_add(Weight::from_ref_time(103_738 as u64).saturating_mul(s as u64)) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(1_480 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 47_483 nanoseconds. + Weight::from_ref_time(37_293_379) + // Standard Error: 796 + .saturating_add(Weight::from_ref_time(118_230).saturating_mul(s.into())) + // Standard Error: 7 + .saturating_add(Weight::from_ref_time(1_692).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) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { - // Minimum execution time: 30_092 nanoseconds. - Weight::from_ref_time(32_588_553 as u64) - // Standard Error: 1_203 - .saturating_add(Weight::from_ref_time(88_907 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 32_427 nanoseconds. + Weight::from_ref_time(35_007_792) + // Standard Error: 1_114 + .saturating_add(Weight::from_ref_time(93_830).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Multisig Multisigs (r:1 w:1) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { - // Minimum execution time: 21_743 nanoseconds. - Weight::from_ref_time(23_807_430 as u64) - // Standard Error: 828 - .saturating_add(Weight::from_ref_time(75_548 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 22_891 nanoseconds. + Weight::from_ref_time(24_948_736) + // Standard Error: 731 + .saturating_add(Weight::from_ref_time(86_594).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) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { - // Minimum execution time: 29_786 nanoseconds. - Weight::from_ref_time(32_090_251 as u64) - // Standard Error: 904 - .saturating_add(Weight::from_ref_time(84_395 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 32_571 nanoseconds. + Weight::from_ref_time(34_813_263) + // Standard Error: 1_000 + .saturating_add(Weight::from_ref_time(89_038).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/rococo/src/weights/pallet_nis.rs b/runtime/rococo/src/weights/pallet_nis.rs new file mode 100644 index 000000000000..290ff03b5cee --- /dev/null +++ b/runtime/rococo/src/weights/pallet_nis.rs @@ -0,0 +1,120 @@ +// Copyright 2017-2022 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_nis` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! 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 +// benchmark +// pallet +// --chain=rococo-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_nis +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --header=./file_header.txt +// --output=./runtime/rococo/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_nis`. +pub struct WeightInfo(PhantomData); +impl pallet_nis::WeightInfo for WeightInfo { + // Storage: Nis Queues (r:1 w:1) + // Storage: Nis QueueTotals (r:1 w:1) + /// The range of component `l` is `[0, 999]`. + fn place_bid(l: u32, ) -> Weight { + // Minimum execution time: 34_707 nanoseconds. + Weight::from_ref_time(35_880_660) + // Standard Error: 725 + .saturating_add(Weight::from_ref_time(81_374).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: Nis Queues (r:1 w:1) + // Storage: Nis QueueTotals (r:1 w:1) + fn place_bid_max() -> Weight { + // Minimum execution time: 108_496 nanoseconds. + Weight::from_ref_time(110_211_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: Nis Queues (r:1 w:1) + // Storage: Nis QueueTotals (r:1 w:1) + /// The range of component `l` is `[1, 1000]`. + fn retract_bid(l: u32, ) -> Weight { + // Minimum execution time: 40_864 nanoseconds. + Weight::from_ref_time(36_898_403) + // Standard Error: 674 + .saturating_add(Weight::from_ref_time(61_925).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: Nis Summary (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn fund_deficit() -> Weight { + // Minimum execution time: 42_435 nanoseconds. + Weight::from_ref_time(43_079_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + // Storage: Nis Receipts (r:1 w:1) + // Storage: Nis Summary (r:1 w:1) + // Storage: NisCounterpartBalances Account (r:1 w:1) + // Storage: NisCounterpartBalances TotalIssuance (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn thaw() -> Weight { + // Minimum execution time: 62_105 nanoseconds. + Weight::from_ref_time(62_865_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } + // Storage: Nis Summary (r:1 w:1) + // Storage: System Account (r:1 w:0) + // Storage: Nis QueueTotals (r:1 w:1) + fn process_queues() -> Weight { + // Minimum execution time: 33_732 nanoseconds. + Weight::from_ref_time(34_695_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: Nis Queues (r:1 w:1) + fn process_queue() -> Weight { + // Minimum execution time: 4_335 nanoseconds. + Weight::from_ref_time(4_532_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + // Storage: System Account (r:1 w:0) + // Storage: Nis Receipts (r:0 w:1) + fn process_bid() -> Weight { + // Minimum execution time: 13_095 nanoseconds. + Weight::from_ref_time(13_222_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/runtime/rococo/src/weights/pallet_preimage.rs b/runtime/rococo/src/weights/pallet_preimage.rs index a3c15353ec6e..b3ed4df82dcd 100644 --- a/runtime/rococo/src/weights/pallet_preimage.rs +++ b/runtime/rococo/src/weights/pallet_preimage.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_preimage` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -48,99 +48,99 @@ impl pallet_preimage::WeightInfo for WeightInfo { // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { - // Minimum execution time: 28_627 nanoseconds. - Weight::from_ref_time(28_863_000 as u64) + // Minimum execution time: 30_655 nanoseconds. + Weight::from_ref_time(30_996_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_343 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_385).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { - // Minimum execution time: 19_969 nanoseconds. - Weight::from_ref_time(20_415_000 as u64) + // Minimum execution time: 21_708 nanoseconds. + Weight::from_ref_time(22_146_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_343 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_383).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { - // Minimum execution time: 18_634 nanoseconds. - Weight::from_ref_time(19_004_000 as u64) + // Minimum execution time: 19_870 nanoseconds. + Weight::from_ref_time(20_144_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_346 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_380).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_preimage() -> Weight { - // Minimum execution time: 41_505 nanoseconds. - Weight::from_ref_time(42_764_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_859 nanoseconds. + Weight::from_ref_time(42_636_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_no_deposit_preimage() -> Weight { - // Minimum execution time: 28_640 nanoseconds. - Weight::from_ref_time(30_140_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 28_404 nanoseconds. + Weight::from_ref_time(29_652_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_preimage() -> Weight { - // Minimum execution time: 26_358 nanoseconds. - Weight::from_ref_time(27_371_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 27_624 nanoseconds. + Weight::from_ref_time(28_698_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_no_deposit_preimage() -> Weight { - // Minimum execution time: 14_281 nanoseconds. - Weight::from_ref_time(15_392_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 14_331 nanoseconds. + Weight::from_ref_time(15_652_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_unnoted_preimage() -> Weight { - // Minimum execution time: 17_828 nanoseconds. - Weight::from_ref_time(18_469_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 19_440 nanoseconds. + Weight::from_ref_time(20_277_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_requested_preimage() -> Weight { - // Minimum execution time: 8_776 nanoseconds. - Weight::from_ref_time(9_054_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_846 nanoseconds. + Weight::from_ref_time(10_010_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_preimage() -> Weight { - // Minimum execution time: 26_343 nanoseconds. - Weight::from_ref_time(27_704_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 26_185 nanoseconds. + Weight::from_ref_time(28_297_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_unnoted_preimage() -> Weight { - // Minimum execution time: 8_730 nanoseconds. - Weight::from_ref_time(9_214_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_670 nanoseconds. + Weight::from_ref_time(9_793_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_multi_referenced_preimage() -> Weight { - // Minimum execution time: 8_970 nanoseconds. - Weight::from_ref_time(9_308_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_641 nanoseconds. + Weight::from_ref_time(10_028_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/rococo/src/weights/pallet_proxy.rs b/runtime/rococo/src/weights/pallet_proxy.rs index cace8999b42f..28c4d505b440 100644 --- a/runtime/rococo/src/weights/pallet_proxy.rs +++ b/runtime/rococo/src/weights/pallet_proxy.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_proxy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -47,11 +47,11 @@ impl pallet_proxy::WeightInfo for WeightInfo { // Storage: Proxy Proxies (r:1 w:0) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { - // Minimum execution time: 19_349 nanoseconds. - Weight::from_ref_time(20_710_623 as u64) - // Standard Error: 1_351 - .saturating_add(Weight::from_ref_time(52_752 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 20_810 nanoseconds. + Weight::from_ref_time(22_058_995) + // Standard Error: 1_314 + .saturating_add(Weight::from_ref_time(49_758).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) @@ -59,42 +59,40 @@ impl pallet_proxy::WeightInfo for WeightInfo { /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 37_890 nanoseconds. - Weight::from_ref_time(37_761_529 as u64) - // Standard Error: 2_006 - .saturating_add(Weight::from_ref_time(126_746 as u64).saturating_mul(a as u64)) - // Standard Error: 2_072 - .saturating_add(Weight::from_ref_time(28_850 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_095 nanoseconds. + Weight::from_ref_time(40_760_444) + // Standard Error: 1_902 + .saturating_add(Weight::from_ref_time(121_726).saturating_mul(a.into())) + // Standard Error: 1_965 + .saturating_add(Weight::from_ref_time(27_217).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) // Storage: System Account (r:1 w:1) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn remove_announcement(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 25_409 nanoseconds. - Weight::from_ref_time(27_189_943 as u64) - // Standard Error: 2_128 - .saturating_add(Weight::from_ref_time(106_009 as u64).saturating_mul(a as u64)) - // Standard Error: 2_199 - .saturating_add(Weight::from_ref_time(2_285 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 28_171 nanoseconds. + Weight::from_ref_time(28_841_253) + // Standard Error: 1_874 + .saturating_add(Weight::from_ref_time(125_781).saturating_mul(a.into())) + // Standard Error: 1_936 + .saturating_add(Weight::from_ref_time(2_670).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) // Storage: System Account (r:1 w:1) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. - fn reject_announcement(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 25_412 nanoseconds. - Weight::from_ref_time(26_386_788 as u64) - // Standard Error: 1_834 - .saturating_add(Weight::from_ref_time(135_933 as u64).saturating_mul(a as u64)) - // Standard Error: 1_895 - .saturating_add(Weight::from_ref_time(11_946 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + fn reject_announcement(a: u32, _p: u32, ) -> Weight { + // Minimum execution time: 27_468 nanoseconds. + Weight::from_ref_time(28_942_120) + // Standard Error: 1_947 + .saturating_add(Weight::from_ref_time(123_103).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) // Storage: Proxy Announcements (r:1 w:1) @@ -102,64 +100,64 @@ impl pallet_proxy::WeightInfo for WeightInfo { /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 33_674 nanoseconds. - Weight::from_ref_time(34_928_865 as u64) - // Standard Error: 1_877 - .saturating_add(Weight::from_ref_time(114_320 as u64).saturating_mul(a as u64)) - // Standard Error: 1_939 - .saturating_add(Weight::from_ref_time(33_723 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 35_976 nanoseconds. + Weight::from_ref_time(37_563_863) + // Standard Error: 2_117 + .saturating_add(Weight::from_ref_time(119_149).saturating_mul(a.into())) + // Standard Error: 2_187 + .saturating_add(Weight::from_ref_time(25_508).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) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { - // Minimum execution time: 26_886 nanoseconds. - Weight::from_ref_time(28_261_342 as u64) - // Standard Error: 1_938 - .saturating_add(Weight::from_ref_time(84_834 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_491 nanoseconds. + Weight::from_ref_time(30_669_205) + // Standard Error: 7_827 + .saturating_add(Weight::from_ref_time(107_910).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) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { - // Minimum execution time: 27_043 nanoseconds. - Weight::from_ref_time(28_490_904 as u64) - // Standard Error: 2_037 - .saturating_add(Weight::from_ref_time(89_429 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 28_540 nanoseconds. + Weight::from_ref_time(30_427_231) + // Standard Error: 2_132 + .saturating_add(Weight::from_ref_time(99_091).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) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { - // Minimum execution time: 23_223 nanoseconds. - Weight::from_ref_time(24_336_319 as u64) - // Standard Error: 1_732 - .saturating_add(Weight::from_ref_time(62_231 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 25_048 nanoseconds. + Weight::from_ref_time(26_473_067) + // Standard Error: 1_843 + .saturating_add(Weight::from_ref_time(49_189).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) // Storage: Proxy Proxies (r:1 w:1) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { - // Minimum execution time: 29_651 nanoseconds. - Weight::from_ref_time(31_071_450 as u64) - // Standard Error: 1_749 - .saturating_add(Weight::from_ref_time(43_722 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 32_211 nanoseconds. + Weight::from_ref_time(33_648_748) + // Standard Error: 1_805 + .saturating_add(Weight::from_ref_time(33_839).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Proxy Proxies (r:1 w:1) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { - // Minimum execution time: 24_984 nanoseconds. - Weight::from_ref_time(25_992_953 as u64) - // Standard Error: 1_517 - .saturating_add(Weight::from_ref_time(37_535 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_953 nanoseconds. + Weight::from_ref_time(28_094_465) + // Standard Error: 1_745 + .saturating_add(Weight::from_ref_time(50_255).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/rococo/src/weights/pallet_scheduler.rs b/runtime/rococo/src/weights/pallet_scheduler.rs index 9235b53bc99f..1db3bad4fe24 100644 --- a/runtime/rococo/src/weights/pallet_scheduler.rs +++ b/runtime/rococo/src/weights/pallet_scheduler.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_scheduler` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -46,95 +46,95 @@ pub struct WeightInfo(PhantomData); impl pallet_scheduler::WeightInfo for WeightInfo { // Storage: Scheduler IncompleteSince (r:1 w:1) fn service_agendas_base() -> Weight { - // Minimum execution time: 4_557 nanoseconds. - Weight::from_ref_time(4_735_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_043 nanoseconds. + Weight::from_ref_time(5_244_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 50]`. fn service_agenda_base(s: u32, ) -> Weight { - // Minimum execution time: 4_123 nanoseconds. - Weight::from_ref_time(7_485_674 as u64) - // Standard Error: 2_415 - .saturating_add(Weight::from_ref_time(707_572 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_639 nanoseconds. + Weight::from_ref_time(8_090_010) + // Standard Error: 2_457 + .saturating_add(Weight::from_ref_time(676_184).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } fn service_task_base() -> Weight { - // Minimum execution time: 9_030 nanoseconds. - Weight::from_ref_time(9_340_000 as u64) + // Minimum execution time: 9_929 nanoseconds. + Weight::from_ref_time(10_183_000) } // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) /// The range of component `s` is `[128, 4194304]`. fn service_task_fetched(s: u32, ) -> Weight { - // Minimum execution time: 20_581 nanoseconds. - Weight::from_ref_time(20_784_000 as u64) - // Standard Error: 1 - .saturating_add(Weight::from_ref_time(1_249 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 22_509 nanoseconds. + Weight::from_ref_time(22_860_000) + // Standard Error: 11 + .saturating_add(Weight::from_ref_time(1_421).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:0 w:1) fn service_task_named() -> Weight { - // Minimum execution time: 10_448 nanoseconds. - Weight::from_ref_time(10_764_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_173 nanoseconds. + Weight::from_ref_time(11_521_000) + .saturating_add(T::DbWeight::get().writes(1)) } fn service_task_periodic() -> Weight { - // Minimum execution time: 9_244 nanoseconds. - Weight::from_ref_time(9_450_000 as u64) + // Minimum execution time: 10_076 nanoseconds. + Weight::from_ref_time(10_417_000) } fn execute_dispatch_signed() -> Weight { - // Minimum execution time: 4_183 nanoseconds. - Weight::from_ref_time(4_335_000 as u64) + // Minimum execution time: 4_690 nanoseconds. + Weight::from_ref_time(4_867_000) } fn execute_dispatch_unsigned() -> Weight { - // Minimum execution time: 4_242 nanoseconds. - Weight::from_ref_time(4_436_000 as u64) + // Minimum execution time: 4_643 nanoseconds. + Weight::from_ref_time(4_842_000) } // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 49]`. fn schedule(s: u32, ) -> Weight { - // Minimum execution time: 16_915 nanoseconds. - Weight::from_ref_time(21_627_553 as u64) - // Standard Error: 2_885 - .saturating_add(Weight::from_ref_time(728_852 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 18_329 nanoseconds. + Weight::from_ref_time(22_414_395) + // Standard Error: 2_786 + .saturating_add(Weight::from_ref_time(704_728).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) // Storage: Scheduler Lookup (r:0 w:1) /// The range of component `s` is `[1, 50]`. fn cancel(s: u32, ) -> Weight { - // Minimum execution time: 20_645 nanoseconds. - Weight::from_ref_time(21_916_728 as u64) - // Standard Error: 2_121 - .saturating_add(Weight::from_ref_time(726_255 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 21_231 nanoseconds. + Weight::from_ref_time(22_817_349) + // Standard Error: 2_170 + .saturating_add(Weight::from_ref_time(686_531).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 49]`. fn schedule_named(s: u32, ) -> Weight { - // Minimum execution time: 19_875 nanoseconds. - Weight::from_ref_time(24_957_647 as u64) - // Standard Error: 3_447 - .saturating_add(Weight::from_ref_time(756_011 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 21_425 nanoseconds. + Weight::from_ref_time(26_109_642) + // Standard Error: 3_160 + .saturating_add(Weight::from_ref_time(722_106).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[1, 50]`. fn cancel_named(s: u32, ) -> Weight { - // Minimum execution time: 20_760 nanoseconds. - Weight::from_ref_time(23_427_367 as u64) - // Standard Error: 2_686 - .saturating_add(Weight::from_ref_time(741_188 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 21_601 nanoseconds. + Weight::from_ref_time(24_205_883) + // Standard Error: 2_248 + .saturating_add(Weight::from_ref_time(712_003).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/rococo/src/weights/pallet_timestamp.rs b/runtime/rococo/src/weights/pallet_timestamp.rs index f4e3c4ef5f4b..51dea5b319dc 100644 --- a/runtime/rococo/src/weights/pallet_timestamp.rs +++ b/runtime/rococo/src/weights/pallet_timestamp.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_timestamp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -47,13 +47,13 @@ impl pallet_timestamp::WeightInfo for WeightInfo { // Storage: Timestamp Now (r:1 w:1) // Storage: Babe CurrentSlot (r:1 w:0) fn set() -> Weight { - // Minimum execution time: 9_159 nanoseconds. - Weight::from_ref_time(9_363_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_501 nanoseconds. + Weight::from_ref_time(10_880_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } fn on_finalize() -> Weight { - // Minimum execution time: 3_854 nanoseconds. - Weight::from_ref_time(3_959_000 as u64) + // Minimum execution time: 4_388 nanoseconds. + Weight::from_ref_time(4_540_000) } } diff --git a/runtime/rococo/src/weights/pallet_tips.rs b/runtime/rococo/src/weights/pallet_tips.rs index 40fcba022275..89fa89fc5511 100644 --- a/runtime/rococo/src/weights/pallet_tips.rs +++ b/runtime/rococo/src/weights/pallet_tips.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_tips` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -48,20 +48,20 @@ impl pallet_tips::WeightInfo for WeightInfo { // Storage: Tips Tips (r:1 w:1) /// The range of component `r` is `[0, 16384]`. fn report_awesome(r: u32, ) -> Weight { - // Minimum execution time: 28_992 nanoseconds. - Weight::from_ref_time(30_902_302 as u64) - // Standard Error: 6 - .saturating_add(Weight::from_ref_time(1_812 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 31_819 nanoseconds. + Weight::from_ref_time(37_509_130) + // Standard Error: 32 + .saturating_add(Weight::from_ref_time(1_498).saturating_mul(r.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) fn retract_tip() -> Weight { - // Minimum execution time: 28_865 nanoseconds. - Weight::from_ref_time(29_465_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 30_639 nanoseconds. + Weight::from_ref_time(31_311_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Members (r:1 w:0) // Storage: Tips Reasons (r:1 w:1) @@ -69,25 +69,25 @@ impl pallet_tips::WeightInfo for WeightInfo { /// The range of component `r` is `[0, 16384]`. /// The range of component `t` is `[1, 19]`. fn tip_new(r: u32, t: u32, ) -> Weight { - // Minimum execution time: 22_554 nanoseconds. - Weight::from_ref_time(21_588_889 as u64) - // Standard Error: 5 - .saturating_add(Weight::from_ref_time(1_684 as u64).saturating_mul(r as u64)) - // Standard Error: 5_031 - .saturating_add(Weight::from_ref_time(137_050 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 24_210 nanoseconds. + Weight::from_ref_time(22_697_785) + // Standard Error: 6 + .saturating_add(Weight::from_ref_time(1_735).saturating_mul(r.into())) + // Standard Error: 5_408 + .saturating_add(Weight::from_ref_time(160_994).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: PhragmenElection Members (r:1 w:0) // Storage: Tips Tips (r:1 w:1) /// The range of component `t` is `[1, 19]`. fn tip(t: u32, ) -> Weight { - // Minimum execution time: 14_818 nanoseconds. - Weight::from_ref_time(15_146_027 as u64) - // Standard Error: 1_730 - .saturating_add(Weight::from_ref_time(153_924 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 16_280 nanoseconds. + Weight::from_ref_time(16_568_900) + // Standard Error: 1_763 + .saturating_add(Weight::from_ref_time(147_225).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Tips Tips (r:1 w:1) // Storage: PhragmenElection Members (r:1 w:0) @@ -95,22 +95,22 @@ impl pallet_tips::WeightInfo for WeightInfo { // Storage: Tips Reasons (r:0 w:1) /// The range of component `t` is `[1, 19]`. fn close_tip(t: u32, ) -> Weight { - // Minimum execution time: 44_644 nanoseconds. - Weight::from_ref_time(46_503_793 as u64) - // Standard Error: 5_514 - .saturating_add(Weight::from_ref_time(136_316 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 47_536 nanoseconds. + Weight::from_ref_time(49_081_421) + // Standard Error: 5_332 + .saturating_add(Weight::from_ref_time(157_457).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Tips Tips (r:1 w:1) // Storage: Tips Reasons (r:0 w:1) /// The range of component `t` is `[1, 19]`. fn slash_tip(t: u32, ) -> Weight { - // Minimum execution time: 18_898 nanoseconds. - Weight::from_ref_time(19_650_499 as u64) - // Standard Error: 1_216 - .saturating_add(Weight::from_ref_time(39_484 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 20_372 nanoseconds. + Weight::from_ref_time(21_245_012) + // Standard Error: 1_586 + .saturating_add(Weight::from_ref_time(28_121).saturating_mul(t.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/rococo/src/weights/pallet_treasury.rs b/runtime/rococo/src/weights/pallet_treasury.rs index 035eeb5080b2..7d21f7370818 100644 --- a/runtime/rococo/src/weights/pallet_treasury.rs +++ b/runtime/rococo/src/weights/pallet_treasury.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_treasury` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -45,56 +45,58 @@ use sp_std::marker::PhantomData; pub struct WeightInfo(PhantomData); impl pallet_treasury::WeightInfo for WeightInfo { fn spend() -> Weight { - // Minimum execution time: 170 nanoseconds. - Weight::from_ref_time(193_000 as u64) + // Minimum execution time: 175 nanoseconds. + Weight::from_ref_time(187_000) } // Storage: Treasury ProposalCount (r:1 w:1) // Storage: Treasury Proposals (r:0 w:1) fn propose_spend() -> Weight { - // Minimum execution time: 26_763 nanoseconds. - Weight::from_ref_time(27_128_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 28_393 nanoseconds. + Weight::from_ref_time(28_748_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Treasury Proposals (r:1 w:1) // Storage: System Account (r:1 w:1) fn reject_proposal() -> Weight { - // Minimum execution time: 37_824 nanoseconds. - Weight::from_ref_time(38_527_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_725 nanoseconds. + Weight::from_ref_time(41_358_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Treasury Proposals (r:1 w:0) // Storage: Treasury Approvals (r:1 w:1) /// The range of component `p` is `[0, 99]`. fn approve_proposal(p: u32, ) -> Weight { - // Minimum execution time: 10_008 nanoseconds. - Weight::from_ref_time(13_421_017 as u64) - // Standard Error: 1_118 - .saturating_add(Weight::from_ref_time(41_405 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_469 nanoseconds. + Weight::from_ref_time(14_262_283) + // Standard Error: 1_154 + .saturating_add(Weight::from_ref_time(49_923).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) fn remove_approval() -> Weight { - // Minimum execution time: 7_923 nanoseconds. - Weight::from_ref_time(8_051_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 8_639 nanoseconds. + Weight::from_ref_time(8_938_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } + // Storage: Treasury Inactive (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: Treasury Approvals (r:1 w:1) // Storage: Bounties BountyApprovals (r:1 w:1) // Storage: System Account (r:1 w:1) // Storage: Treasury Proposals (r:2 w:2) /// The range of component `p` is `[0, 100]`. fn on_initialize_proposals(p: u32, ) -> Weight { - // Minimum execution time: 47_732 nanoseconds. - Weight::from_ref_time(57_707_558 as u64) - // Standard Error: 22_526 - .saturating_add(Weight::from_ref_time(24_251_356 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(p as u64))) + // Minimum execution time: 54_923 nanoseconds. + Weight::from_ref_time(62_244_976) + // Standard Error: 22_558 + .saturating_add(Weight::from_ref_time(26_414_045).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(5)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(p.into()))) } } diff --git a/runtime/rococo/src/weights/pallet_utility.rs b/runtime/rococo/src/weights/pallet_utility.rs index b40c3847fa1a..cebae4e74290 100644 --- a/runtime/rococo/src/weights/pallet_utility.rs +++ b/runtime/rococo/src/weights/pallet_utility.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_utility` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -46,31 +46,31 @@ pub struct WeightInfo(PhantomData); impl pallet_utility::WeightInfo for WeightInfo { /// The range of component `c` is `[0, 1000]`. fn batch(c: u32, ) -> Weight { - // Minimum execution time: 11_223 nanoseconds. - Weight::from_ref_time(20_119_148 as u64) - // Standard Error: 2_555 - .saturating_add(Weight::from_ref_time(3_607_766 as u64).saturating_mul(c as u64)) + // Minimum execution time: 12_481 nanoseconds. + Weight::from_ref_time(44_659_278) + // Standard Error: 6_160 + .saturating_add(Weight::from_ref_time(3_901_051).saturating_mul(c.into())) } fn as_derivative() -> Weight { - // Minimum execution time: 6_008 nanoseconds. - Weight::from_ref_time(6_173_000 as u64) + // Minimum execution time: 6_619 nanoseconds. + Weight::from_ref_time(6_850_000) } /// The range of component `c` is `[0, 1000]`. fn batch_all(c: u32, ) -> Weight { - // Minimum execution time: 11_021 nanoseconds. - Weight::from_ref_time(20_490_374 as u64) - // Standard Error: 2_716 - .saturating_add(Weight::from_ref_time(3_772_423 as u64).saturating_mul(c as u64)) + // Minimum execution time: 12_117 nanoseconds. + Weight::from_ref_time(16_304_194) + // Standard Error: 3_446 + .saturating_add(Weight::from_ref_time(4_140_565).saturating_mul(c.into())) } fn dispatch_as() -> Weight { - // Minimum execution time: 13_528 nanoseconds. - Weight::from_ref_time(13_792_000 as u64) + // Minimum execution time: 14_338 nanoseconds. + Weight::from_ref_time(14_549_000) } /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { - // Minimum execution time: 11_349 nanoseconds. - Weight::from_ref_time(14_365_442 as u64) - // Standard Error: 2_571 - .saturating_add(Weight::from_ref_time(3_618_172 as u64).saturating_mul(c as u64)) + // Minimum execution time: 12_239 nanoseconds. + Weight::from_ref_time(33_393_732) + // Standard Error: 5_754 + .saturating_add(Weight::from_ref_time(3_959_277).saturating_mul(c.into())) } } diff --git a/runtime/rococo/src/weights/pallet_vesting.rs b/runtime/rococo/src/weights/pallet_vesting.rs index b080efd9fe5e..63f4c7fc1aac 100644 --- a/runtime/rococo/src/weights/pallet_vesting.rs +++ b/runtime/rococo/src/weights/pallet_vesting.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_vesting` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -49,28 +49,28 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_locked(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 36_043 nanoseconds. - Weight::from_ref_time(34_972_032 as u64) - // Standard Error: 1_941 - .saturating_add(Weight::from_ref_time(49_687 as u64).saturating_mul(l as u64)) - // Standard Error: 3_453 - .saturating_add(Weight::from_ref_time(83_831 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 39_572 nanoseconds. + Weight::from_ref_time(38_862_769) + // Standard Error: 1_216 + .saturating_add(Weight::from_ref_time(49_034).saturating_mul(l.into())) + // Standard Error: 2_164 + .saturating_add(Weight::from_ref_time(62_799).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_unlocked(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 35_347 nanoseconds. - Weight::from_ref_time(34_849_877 as u64) - // Standard Error: 1_067 - .saturating_add(Weight::from_ref_time(44_302 as u64).saturating_mul(l as u64)) - // Standard Error: 1_899 - .saturating_add(Weight::from_ref_time(60_583 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 38_591 nanoseconds. + Weight::from_ref_time(38_329_101) + // Standard Error: 1_137 + .saturating_add(Weight::from_ref_time(38_643).saturating_mul(l.into())) + // Standard Error: 2_024 + .saturating_add(Weight::from_ref_time(59_770).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -78,14 +78,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 35_931 nanoseconds. - Weight::from_ref_time(34_563_114 as u64) - // Standard Error: 1_021 - .saturating_add(Weight::from_ref_time(51_575 as u64).saturating_mul(l as u64)) - // Standard Error: 1_817 - .saturating_add(Weight::from_ref_time(77_319 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 38_082 nanoseconds. + Weight::from_ref_time(38_067_162) + // Standard Error: 1_151 + .saturating_add(Weight::from_ref_time(50_199).saturating_mul(l.into())) + // Standard Error: 2_048 + .saturating_add(Weight::from_ref_time(62_862).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -93,14 +93,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 35_236 nanoseconds. - Weight::from_ref_time(34_400_789 as u64) - // Standard Error: 1_024 - .saturating_add(Weight::from_ref_time(42_895 as u64).saturating_mul(l as u64)) - // Standard Error: 1_822 - .saturating_add(Weight::from_ref_time(63_821 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 38_296 nanoseconds. + Weight::from_ref_time(37_609_579) + // Standard Error: 1_132 + .saturating_add(Weight::from_ref_time(46_533).saturating_mul(l.into())) + // Standard Error: 2_014 + .saturating_add(Weight::from_ref_time(62_393).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:1 w:1) @@ -108,14 +108,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[0, 27]`. fn vested_transfer(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 49_264 nanoseconds. - Weight::from_ref_time(48_873_608 as u64) - // Standard Error: 4_414 - .saturating_add(Weight::from_ref_time(57_567 as u64).saturating_mul(l as u64)) - // Standard Error: 7_854 - .saturating_add(Weight::from_ref_time(59_806 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 53_587 nanoseconds. + Weight::from_ref_time(53_678_770) + // Standard Error: 2_100 + .saturating_add(Weight::from_ref_time(46_947).saturating_mul(l.into())) + // Standard Error: 3_737 + .saturating_add(Weight::from_ref_time(51_077).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:2 w:2) @@ -123,14 +123,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 48_572 nanoseconds. - Weight::from_ref_time(49_272_636 as u64) - // Standard Error: 2_054 - .saturating_add(Weight::from_ref_time(40_021 as u64).saturating_mul(l as u64)) - // Standard Error: 3_654 - .saturating_add(Weight::from_ref_time(27_590 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 52_700 nanoseconds. + Weight::from_ref_time(52_908_933) + // Standard Error: 2_210 + .saturating_add(Weight::from_ref_time(49_102).saturating_mul(l.into())) + // Standard Error: 3_932 + .saturating_add(Weight::from_ref_time(58_885).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -138,14 +138,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 37_312 nanoseconds. - Weight::from_ref_time(36_432_962 as u64) - // Standard Error: 1_100 - .saturating_add(Weight::from_ref_time(45_567 as u64).saturating_mul(l as u64)) - // Standard Error: 2_032 - .saturating_add(Weight::from_ref_time(67_536 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 40_442 nanoseconds. + Weight::from_ref_time(41_740_321) + // Standard Error: 5_138 + .saturating_add(Weight::from_ref_time(11_529).saturating_mul(l.into())) + // Standard Error: 9_489 + .saturating_add(Weight::from_ref_time(51_842).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -153,13 +153,13 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 37_279 nanoseconds. - Weight::from_ref_time(36_099_205 as u64) - // Standard Error: 1_049 - .saturating_add(Weight::from_ref_time(46_654 as u64).saturating_mul(l as u64)) - // Standard Error: 1_939 - .saturating_add(Weight::from_ref_time(80_111 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 40_106 nanoseconds. + Weight::from_ref_time(39_544_780) + // Standard Error: 1_192 + .saturating_add(Weight::from_ref_time(54_551).saturating_mul(l.into())) + // Standard Error: 2_202 + .saturating_add(Weight::from_ref_time(69_561).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/rococo/src/weights/runtime_common_auctions.rs b/runtime/rococo/src/weights/runtime_common_auctions.rs index 9646ff3f7011..e94dfc8ab1f2 100644 --- a/runtime/rococo/src/weights/runtime_common_auctions.rs +++ b/runtime/rococo/src/weights/runtime_common_auctions.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::auctions` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -47,10 +47,10 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Auctions AuctionInfo (r:1 w:1) // Storage: Auctions AuctionCounter (r:1 w:1) fn new_auction() -> Weight { - // Minimum execution time: 16_469 nanoseconds. - Weight::from_ref_time(16_963_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 17_463 nanoseconds. + Weight::from_ref_time(18_023_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Paras ParaLifecycles (r:1 w:0) // Storage: Auctions AuctionCounter (r:1 w:0) @@ -60,10 +60,10 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Auctions ReservedAmounts (r:2 w:2) // Storage: System Account (r:1 w:1) fn bid() -> Weight { - // Minimum execution time: 70_867 nanoseconds. - Weight::from_ref_time(71_812_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 76_507 nanoseconds. + Weight::from_ref_time(77_937_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Auctions AuctionInfo (r:1 w:1) // Storage: Babe NextRandomness (r:1 w:0) @@ -78,19 +78,19 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar Paras (r:1 w:1) fn on_initialize() -> Weight { - // Minimum execution time: 14_379_395 nanoseconds. - Weight::from_ref_time(14_660_269_000 as u64) - .saturating_add(T::DbWeight::get().reads(3683 as u64)) - .saturating_add(T::DbWeight::get().writes(3678 as u64)) + // Minimum execution time: 15_416_976 nanoseconds. + Weight::from_ref_time(15_799_478_000) + .saturating_add(T::DbWeight::get().reads(3683)) + .saturating_add(T::DbWeight::get().writes(3678)) } // Storage: Auctions ReservedAmounts (r:37 w:36) // Storage: System Account (r:36 w:36) // Storage: Auctions Winning (r:0 w:3600) // Storage: Auctions AuctionInfo (r:0 w:1) fn cancel_auction() -> Weight { - // Minimum execution time: 4_503_529 nanoseconds. - Weight::from_ref_time(4_632_974_000 as u64) - .saturating_add(T::DbWeight::get().reads(73 as u64)) - .saturating_add(T::DbWeight::get().writes(3673 as u64)) + // Minimum execution time: 4_666_160 nanoseconds. + Weight::from_ref_time(4_785_047_000) + .saturating_add(T::DbWeight::get().reads(73)) + .saturating_add(T::DbWeight::get().writes(3673)) } } diff --git a/runtime/rococo/src/weights/runtime_common_claims.rs b/runtime/rococo/src/weights/runtime_common_claims.rs index 2819000fd44e..f9a06d110eb8 100644 --- a/runtime/rococo/src/weights/runtime_common_claims.rs +++ b/runtime/rococo/src/weights/runtime_common_claims.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::claims` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -52,20 +52,20 @@ impl runtime_common::claims::WeightInfo for WeightInfo< // Storage: System Account (r:1 w:0) // Storage: Balances Locks (r:1 w:1) fn claim() -> Weight { - // Minimum execution time: 139_048 nanoseconds. - Weight::from_ref_time(142_879_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 143_827 nanoseconds. + Weight::from_ref_time(145_893_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Claims Total (r:1 w:1) // Storage: Claims Vesting (r:0 w:1) // Storage: Claims Claims (r:0 w:1) // Storage: Claims Signing (r:0 w:1) fn mint_claim() -> Weight { - // Minimum execution time: 11_289 nanoseconds. - Weight::from_ref_time(11_526_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 12_242 nanoseconds. + Weight::from_ref_time(12_658_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Claims Claims (r:1 w:1) // Storage: Claims Signing (r:1 w:1) @@ -75,10 +75,10 @@ impl runtime_common::claims::WeightInfo for WeightInfo< // Storage: System Account (r:1 w:0) // Storage: Balances Locks (r:1 w:1) fn claim_attest() -> Weight { - // Minimum execution time: 142_402 nanoseconds. - Weight::from_ref_time(144_821_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 147_744 nanoseconds. + Weight::from_ref_time(154_711_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Claims Preclaims (r:1 w:1) // Storage: Claims Signing (r:1 w:1) @@ -89,19 +89,19 @@ impl runtime_common::claims::WeightInfo for WeightInfo< // Storage: System Account (r:1 w:0) // Storage: Balances Locks (r:1 w:1) fn attest() -> Weight { - // Minimum execution time: 64_758 nanoseconds. - Weight::from_ref_time(66_207_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 68_784 nanoseconds. + Weight::from_ref_time(71_659_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Claims Claims (r:1 w:2) // Storage: Claims Vesting (r:1 w:2) // Storage: Claims Signing (r:1 w:2) // Storage: Claims Preclaims (r:1 w:1) fn move_claim() -> Weight { - // Minimum execution time: 21_449 nanoseconds. - Weight::from_ref_time(21_840_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 22_829 nanoseconds. + Weight::from_ref_time(23_350_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(7)) } } diff --git a/runtime/rococo/src/weights/runtime_common_crowdloan.rs b/runtime/rococo/src/weights/runtime_common_crowdloan.rs index 2340c33b1260..d41b25458373 100644 --- a/runtime/rococo/src/weights/runtime_common_crowdloan.rs +++ b/runtime/rococo/src/weights/runtime_common_crowdloan.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::crowdloan` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -49,75 +49,77 @@ impl runtime_common::crowdloan::WeightInfo for WeightIn // Storage: Paras ParaLifecycles (r:1 w:0) // Storage: Crowdloan NextFundIndex (r:1 w:1) fn create() -> Weight { - // Minimum execution time: 46_434 nanoseconds. - Weight::from_ref_time(47_883_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 51_117 nanoseconds. + Weight::from_ref_time(51_954_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: Slots Leases (r:1 w:0) // Storage: Auctions AuctionInfo (r:1 w:0) // Storage: System Account (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: Crowdloan EndingsCount (r:1 w:0) // Storage: Crowdloan NewRaise (r:1 w:1) // Storage: unknown [0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291] (r:1 w:1) fn contribute() -> Weight { - // Minimum execution time: 115_616 nanoseconds. - Weight::from_ref_time(117_125_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 123_151 nanoseconds. + Weight::from_ref_time(124_227_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: System Account (r:2 w:2) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: unknown [0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0] (r:1 w:1) fn withdraw() -> Weight { - // Minimum execution time: 54_162 nanoseconds. - Weight::from_ref_time(55_016_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 62_415 nanoseconds. + Weight::from_ref_time(63_853_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `k` is `[0, 1000]`. fn refund(k: u32, ) -> Weight { - // Minimum execution time: 51_334 nanoseconds. - Weight::from_ref_time(52_592_000 as u64) - // Standard Error: 13_105 - .saturating_add(Weight::from_ref_time(17_374_051 as u64).saturating_mul(k as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(k as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(k as u64))) + // Minimum execution time: 65_038 nanoseconds. + Weight::from_ref_time(65_747_000) + // Standard Error: 13_393 + .saturating_add(Weight::from_ref_time(19_554_571).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(3)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(k.into()))) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: System Account (r:1 w:1) fn dissolve() -> Weight { - // Minimum execution time: 35_483 nanoseconds. - Weight::from_ref_time(36_509_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 38_105 nanoseconds. + Weight::from_ref_time(38_974_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Crowdloan Funds (r:1 w:1) fn edit() -> Weight { - // Minimum execution time: 24_605 nanoseconds. - Weight::from_ref_time(25_894_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_626 nanoseconds. + Weight::from_ref_time(27_630_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Crowdloan Funds (r:1 w:0) // Storage: unknown [0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291] (r:1 w:1) fn add_memo() -> Weight { - // Minimum execution time: 31_157 nanoseconds. - Weight::from_ref_time(32_555_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 34_371 nanoseconds. + Weight::from_ref_time(35_698_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Crowdloan Funds (r:1 w:0) // Storage: Crowdloan NewRaise (r:1 w:1) fn poke() -> Weight { - // Minimum execution time: 24_592 nanoseconds. - Weight::from_ref_time(25_684_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_758 nanoseconds. + Weight::from_ref_time(27_782_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Auctions AuctionInfo (r:1 w:0) // Storage: Crowdloan EndingsCount (r:1 w:1) @@ -131,13 +133,13 @@ impl runtime_common::crowdloan::WeightInfo for WeightIn // Storage: System Account (r:2 w:2) /// The range of component `n` is `[2, 100]`. fn on_initialize(n: u32, ) -> Weight { - // Minimum execution time: 102_130 nanoseconds. - Weight::from_ref_time(6_401_092 as u64) - // Standard Error: 46_468 - .saturating_add(Weight::from_ref_time(40_862_949 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(n as u64))) + // Minimum execution time: 108_054 nanoseconds. + Weight::from_ref_time(10_648_303) + // Standard Error: 41_245 + .saturating_add(Weight::from_ref_time(43_476_264).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)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) } } diff --git a/runtime/rococo/src/weights/runtime_common_paras_registrar.rs b/runtime/rococo/src/weights/runtime_common_paras_registrar.rs index 5cc8749813f8..644e1c09d11c 100644 --- a/runtime/rococo/src/weights/runtime_common_paras_registrar.rs +++ b/runtime/rococo/src/weights/runtime_common_paras_registrar.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::paras_registrar` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -48,10 +48,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:0) fn reserve() -> Weight { - // Minimum execution time: 31_697 nanoseconds. - Weight::from_ref_time(32_209_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 32_942 nanoseconds. + Weight::from_ref_time(33_595_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -64,10 +64,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras CurrentCodeHash (r:0 w:1) // Storage: Paras UpcomingParasGenesis (r:0 w:1) fn register() -> Weight { - // Minimum execution time: 7_452_657 nanoseconds. - Weight::from_ref_time(7_575_304_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 7_484_592 nanoseconds. + Weight::from_ref_time(7_658_902_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -80,10 +80,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras CurrentCodeHash (r:0 w:1) // Storage: Paras UpcomingParasGenesis (r:0 w:1) fn force_register() -> Weight { - // Minimum execution time: 7_429_097 nanoseconds. - Weight::from_ref_time(7_573_259_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 7_515_645 nanoseconds. + Weight::from_ref_time(7_643_087_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -92,10 +92,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar PendingSwap (r:0 w:1) fn deregister() -> Weight { - // Minimum execution time: 48_195 nanoseconds. - Weight::from_ref_time(49_027_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 49_790 nanoseconds. + Weight::from_ref_time(51_587_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Registrar Paras (r:1 w:0) // Storage: Paras ParaLifecycles (r:2 w:2) @@ -105,10 +105,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Crowdloan Funds (r:2 w:2) // Storage: Slots Leases (r:2 w:2) fn swap() -> Weight { - // Minimum execution time: 43_201 nanoseconds. - Weight::from_ref_time(43_804_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 45_310 nanoseconds. + Weight::from_ref_time(46_276_000) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras FutureCodeHash (r:1 w:1) // Storage: Paras UpgradeRestrictionSignal (r:1 w:1) @@ -123,20 +123,20 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras FutureCodeUpgrades (r:0 w:1) /// The range of component `b` is `[1, 3145728]`. fn schedule_code_upgrade(b: u32, ) -> Weight { - // Minimum execution time: 42_089 nanoseconds. - Weight::from_ref_time(42_743_000 as u64) + // Minimum execution time: 43_237 nanoseconds. + Weight::from_ref_time(43_868_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_339 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + .saturating_add(Weight::from_ref_time(2_384).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras Heads (r:0 w:1) /// The range of component `b` is `[1, 1048576]`. fn set_current_head(b: u32, ) -> Weight { - // Minimum execution time: 13_554 nanoseconds. - Weight::from_ref_time(13_744_000 as u64) + // Minimum execution time: 14_259 nanoseconds. + Weight::from_ref_time(14_493_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(964 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(972).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/rococo/src/weights/runtime_common_slots.rs b/runtime/rococo/src/weights/runtime_common_slots.rs index 17723f9b93b0..70d81e737670 100644 --- a/runtime/rococo/src/weights/runtime_common_slots.rs +++ b/runtime/rococo/src/weights/runtime_common_slots.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::slots` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -47,40 +47,40 @@ impl runtime_common::slots::WeightInfo for WeightInfo Weight { - // Minimum execution time: 30_626 nanoseconds. - Weight::from_ref_time(31_415_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 33_212 nanoseconds. + Weight::from_ref_time(34_350_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Paras Parachains (r:1 w:0) // Storage: Slots Leases (r:101 w:100) - // Storage: Paras ParaLifecycles (r:101 w:101) + // Storage: Paras ParaLifecycles (r:100 w:100) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar Paras (r:100 w:100) - /// The range of component `c` is `[1, 100]`. - /// The range of component `t` is `[1, 100]`. + /// 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 { - // Minimum execution time: 562_166 nanoseconds. - Weight::from_ref_time(566_185_000 as u64) - // Standard Error: 71_695 - .saturating_add(Weight::from_ref_time(2_078_821 as u64).saturating_mul(c as u64)) - // Standard Error: 71_695 - .saturating_add(Weight::from_ref_time(11_845_926 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(t as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(t as u64))) + // Minimum execution time: 559_683 nanoseconds. + Weight::from_ref_time(560_979_000) + // Standard Error: 71_232 + .saturating_add(Weight::from_ref_time(2_390_966).saturating_mul(c.into())) + // Standard Error: 71_232 + .saturating_add(Weight::from_ref_time(12_651_498).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().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()))) } // Storage: Slots Leases (r:1 w:1) // Storage: System Account (r:8 w:8) fn clear_all_leases() -> Weight { - // Minimum execution time: 92_423 nanoseconds. - Weight::from_ref_time(94_128_000 as u64) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 96_740 nanoseconds. + Weight::from_ref_time(98_440_000) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(9)) } // Storage: Slots Leases (r:1 w:0) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -88,9 +88,9 @@ impl runtime_common::slots::WeightInfo for WeightInfo Weight { - // Minimum execution time: 28_988 nanoseconds. - Weight::from_ref_time(30_069_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 30_791 nanoseconds. + Weight::from_ref_time(31_508_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/rococo/src/weights/runtime_parachains_configuration.rs b/runtime/rococo/src/weights/runtime_parachains_configuration.rs index 7f3057800067..9c76afd9c431 100644 --- a/runtime/rococo/src/weights/runtime_parachains_configuration.rs +++ b/runtime/rococo/src/weights/runtime_parachains_configuration.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::configuration` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -49,54 +49,54 @@ impl runtime_parachains::configuration::WeightInfo for // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_block_number() -> Weight { - // Minimum execution time: 12_597 nanoseconds. - Weight::from_ref_time(13_059_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_720 nanoseconds. + Weight::from_ref_time(13_192_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_u32() -> Weight { - // Minimum execution time: 12_590 nanoseconds. - Weight::from_ref_time(12_953_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_770 nanoseconds. + Weight::from_ref_time(13_095_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_option_u32() -> Weight { - // Minimum execution time: 12_263 nanoseconds. - Weight::from_ref_time(12_730_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_384 nanoseconds. + Weight::from_ref_time(12_755_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_weight() -> Weight { - // Minimum execution time: 12_258 nanoseconds. - Weight::from_ref_time(12_815_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_763 nanoseconds. + Weight::from_ref_time(13_109_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Benchmark Override (r:0 w:0) fn set_hrmp_open_request_ttl() -> Weight { // Minimum execution time: 2_000_000_000 nanoseconds. - Weight::from_ref_time(2_000_000_000_000 as u64) + Weight::from_ref_time(2_000_000_000_000) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_balance() -> Weight { - // Minimum execution time: 12_495 nanoseconds. - Weight::from_ref_time(12_971_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_449 nanoseconds. + Weight::from_ref_time(12_818_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/rococo/src/weights/runtime_parachains_disputes.rs b/runtime/rococo/src/weights/runtime_parachains_disputes.rs index 7d611efb34fb..69c6944e8458 100644 --- a/runtime/rococo/src/weights/runtime_parachains_disputes.rs +++ b/runtime/rococo/src/weights/runtime_parachains_disputes.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::disputes` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -46,8 +46,8 @@ pub struct WeightInfo(PhantomData); impl runtime_parachains::disputes::WeightInfo for WeightInfo { // Storage: ParasDisputes Frozen (r:0 w:1) fn force_unfreeze() -> Weight { - // Minimum execution time: 4_209 nanoseconds. - Weight::from_ref_time(4_281_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_029 nanoseconds. + Weight::from_ref_time(5_281_000) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/rococo/src/weights/runtime_parachains_hrmp.rs b/runtime/rococo/src/weights/runtime_parachains_hrmp.rs index 8937d4a88c9e..2eaad96c03f9 100644 --- a/runtime/rococo/src/weights/runtime_parachains_hrmp.rs +++ b/runtime/rococo/src/weights/runtime_parachains_hrmp.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::hrmp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -54,10 +54,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_init_open_channel() -> Weight { - // Minimum execution time: 39_625 nanoseconds. - Weight::from_ref_time(40_445_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 43_497 nanoseconds. + Weight::from_ref_time(44_266_000) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) // Storage: Configuration ActiveConfig (r:1 w:0) @@ -67,10 +67,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_accept_open_channel() -> Weight { - // Minimum execution time: 39_703 nanoseconds. - Weight::from_ref_time(40_505_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 43_104 nanoseconds. + Weight::from_ref_time(43_527_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Hrmp HrmpChannels (r:1 w:0) // Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) @@ -79,10 +79,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_close_channel() -> Weight { - // Minimum execution time: 36_723 nanoseconds. - Weight::from_ref_time(37_406_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 39_460 nanoseconds. + Weight::from_ref_time(39_694_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127) // Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1) @@ -93,18 +93,18 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// 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 { - // Minimum execution time: 858_127 nanoseconds. - Weight::from_ref_time(867_315_000 as u64) - // Standard Error: 78_610 - .saturating_add(Weight::from_ref_time(2_628_159 as u64).saturating_mul(i as u64)) - // Standard Error: 78_610 - .saturating_add(Weight::from_ref_time(2_715_230 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(e as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(e as u64))) + // Minimum execution time: 897_190 nanoseconds. + Weight::from_ref_time(904_507_000) + // Standard Error: 81_636 + .saturating_add(Weight::from_ref_time(2_799_978).saturating_mul(i.into())) + // Standard Error: 81_636 + .saturating_add(Weight::from_ref_time(2_802_101).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()))) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(i.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(e.into()))) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0) @@ -117,14 +117,14 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpChannels (r:0 w:2) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_open(c: u32, ) -> Weight { - // Minimum execution time: 9_591 nanoseconds. - Weight::from_ref_time(9_702_000 as u64) - // Standard Error: 11_345 - .saturating_add(Weight::from_ref_time(15_504_007 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((7 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((6 as u64).saturating_mul(c as u64))) + // Minimum execution time: 10_531 nanoseconds. + Weight::from_ref_time(1_324_155) + // Standard Error: 21_195 + .saturating_add(Weight::from_ref_time(16_379_005).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()))) } // Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0) // Storage: Hrmp HrmpChannels (r:2 w:2) @@ -134,39 +134,39 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpChannelContents (r:0 w:2) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_close(c: u32, ) -> Weight { - // Minimum execution time: 6_100 nanoseconds. - Weight::from_ref_time(6_209_000 as u64) - // Standard Error: 8_660 - .saturating_add(Weight::from_ref_time(9_565_726 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((5 as u64).saturating_mul(c as u64))) + // Minimum execution time: 6_977 nanoseconds. + Weight::from_ref_time(7_120_000) + // Standard Error: 8_117 + .saturating_add(Weight::from_ref_time(9_994_010).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()))) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) /// The range of component `c` is `[0, 128]`. fn hrmp_cancel_open_request(c: u32, ) -> Weight { - // Minimum execution time: 24_413 nanoseconds. - Weight::from_ref_time(30_943_685 as u64) - // Standard Error: 1_337 - .saturating_add(Weight::from_ref_time(83_692 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 26_652 nanoseconds. + Weight::from_ref_time(32_863_125) + // Standard Error: 1_412 + .saturating_add(Weight::from_ref_time(94_403).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) /// The range of component `c` is `[0, 128]`. fn clean_open_channel_requests(c: u32, ) -> Weight { - // Minimum execution time: 4_110 nanoseconds. - Weight::from_ref_time(2_664_207 as u64) - // Standard Error: 3_639 - .saturating_add(Weight::from_ref_time(2_567_247 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + // Minimum execution time: 4_939 nanoseconds. + Weight::from_ref_time(3_454_397) + // Standard Error: 3_850 + .saturating_add(Weight::from_ref_time(2_648_173).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()))) } // Storage: Paras ParaLifecycles (r:2 w:0) // Storage: Configuration ActiveConfig (r:1 w:0) @@ -180,9 +180,9 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) fn force_open_hrmp_channel() -> Weight { - // Minimum execution time: 51_110 nanoseconds. - Weight::from_ref_time(52_535_000 as u64) - .saturating_add(T::DbWeight::get().reads(14 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 54_190 nanoseconds. + Weight::from_ref_time(54_773_000) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(8)) } } diff --git a/runtime/rococo/src/weights/runtime_parachains_initializer.rs b/runtime/rococo/src/weights/runtime_parachains_initializer.rs index b11f9ca3dedc..12d3c96055f0 100644 --- a/runtime/rococo/src/weights/runtime_parachains_initializer.rs +++ b/runtime/rococo/src/weights/runtime_parachains_initializer.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::initializer` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -47,11 +47,11 @@ impl runtime_parachains::initializer::WeightInfo for We // Storage: System Digest (r:1 w:1) /// The range of component `d` is `[0, 65536]`. fn force_approve(d: u32, ) -> Weight { - // Minimum execution time: 7_175 nanoseconds. - Weight::from_ref_time(10_442_900 as u64) + // Minimum execution time: 8_271 nanoseconds. + Weight::from_ref_time(11_209_011) // Standard Error: 4 - .saturating_add(Weight::from_ref_time(1_297 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(1_311).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/rococo/src/weights/runtime_parachains_paras.rs b/runtime/rococo/src/weights/runtime_parachains_paras.rs index 3daf4005d7b5..c2e295779191 100644 --- a/runtime/rococo/src/weights/runtime_parachains_paras.rs +++ b/runtime/rococo/src/weights/runtime_parachains_paras.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::paras` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -52,21 +52,21 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras CodeByHash (r:0 w:1) /// The range of component `c` is `[1, 3145728]`. fn force_set_current_code(c: u32, ) -> Weight { - // Minimum execution time: 35_999 nanoseconds. - Weight::from_ref_time(36_498_000 as u64) + // Minimum execution time: 37_151 nanoseconds. + Weight::from_ref_time(37_533_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_327 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + .saturating_add(Weight::from_ref_time(2_366).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) /// The range of component `s` is `[1, 1048576]`. fn force_set_current_head(s: u32, ) -> Weight { - // Minimum execution time: 12_171 nanoseconds. - Weight::from_ref_time(12_504_000 as u64) + // Minimum execution time: 13_523 nanoseconds. + Weight::from_ref_time(13_824_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(964 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(964).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: Paras FutureCodeHash (r:1 w:1) @@ -81,61 +81,61 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras UpgradeRestrictionSignal (r:0 w:1) /// The range of component `c` is `[1, 3145728]`. fn force_schedule_code_upgrade(c: u32, ) -> Weight { - // Minimum execution time: 60_066 nanoseconds. - Weight::from_ref_time(60_514_000 as u64) + // Minimum execution time: 62_772 nanoseconds. + Weight::from_ref_time(63_277_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_347 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + .saturating_add(Weight::from_ref_time(2_390).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras FutureCodeUpgrades (r:1 w:0) // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) /// The range of component `s` is `[1, 1048576]`. fn force_note_new_head(s: u32, ) -> Weight { - // Minimum execution time: 17_871 nanoseconds. - Weight::from_ref_time(18_032_000 as u64) + // Minimum execution time: 19_830 nanoseconds. + Weight::from_ref_time(20_085_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(965 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(966).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) // Storage: Paras ActionsQueue (r:1 w:1) fn force_queue_action() -> Weight { - // Minimum execution time: 22_888 nanoseconds. - Weight::from_ref_time(23_397_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 24_757 nanoseconds. + Weight::from_ref_time(25_099_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras PvfActiveVoteMap (r:1 w:0) // Storage: Paras CodeByHash (r:1 w:1) /// The range of component `c` is `[1, 3145728]`. fn add_trusted_validation_code(c: u32, ) -> Weight { - // Minimum execution time: 8_349 nanoseconds. - Weight::from_ref_time(8_438_000 as u64) + // Minimum execution time: 9_151 nanoseconds. + Weight::from_ref_time(9_282_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_334 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(2_374).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras CodeByHashRefs (r:1 w:0) // Storage: Paras CodeByHash (r:0 w:1) fn poke_unused_validation_code() -> Weight { - // Minimum execution time: 6_533 nanoseconds. - Weight::from_ref_time(6_733_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 7_359 nanoseconds. + Weight::from_ref_time(7_540_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) // Storage: Paras PvfActiveVoteMap (r:1 w:1) fn include_pvf_check_statement() -> Weight { - // Minimum execution time: 93_496 nanoseconds. - Weight::from_ref_time(96_071_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 95_056 nanoseconds. + Weight::from_ref_time(96_608_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) @@ -146,10 +146,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: System Digest (r:1 w:1) // Storage: Paras FutureCodeUpgrades (r:0 w:100) fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { - // Minimum execution time: 628_935 nanoseconds. - Weight::from_ref_time(637_577_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(104 as u64)) + // Minimum execution time: 669_650 nanoseconds. + Weight::from_ref_time(676_168_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(104)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) @@ -161,10 +161,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras UpgradeGoAheadSignal (r:0 w:100) // Storage: Paras FutureCodeHash (r:0 w:100) fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { - // Minimum execution time: 605_260 nanoseconds. - Weight::from_ref_time(609_252_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(204 as u64)) + // Minimum execution time: 630_406 nanoseconds. + Weight::from_ref_time(637_880_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(204)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) @@ -173,10 +173,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras PvfActiveVoteList (r:1 w:1) // Storage: Paras ActionsQueue (r:1 w:1) fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { - // Minimum execution time: 500_559 nanoseconds. - Weight::from_ref_time(504_952_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 520_712 nanoseconds. + Weight::from_ref_time(526_679_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Configuration ActiveConfig (r:1 w:0) // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) @@ -189,9 +189,9 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras CurrentCodeHash (r:0 w:100) // Storage: Paras UpcomingParasGenesis (r:0 w:100) fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { - // Minimum execution time: 663_855 nanoseconds. - Weight::from_ref_time(673_507_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(304 as u64)) + // Minimum execution time: 708_950 nanoseconds. + Weight::from_ref_time(714_709_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(304)) } } diff --git a/runtime/rococo/src/weights/runtime_parachains_ump.rs b/runtime/rococo/src/weights/runtime_parachains_ump.rs index 47a9de38d9b2..d8bcb418aef4 100644 --- a/runtime/rococo/src/weights/runtime_parachains_ump.rs +++ b/runtime/rococo/src/weights/runtime_parachains_ump.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::ump` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-16, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! 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 @@ -46,26 +46,26 @@ pub struct WeightInfo(PhantomData); impl runtime_parachains::ump::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 51200]`. fn process_upward_message(s: u32, ) -> Weight { - // Minimum execution time: 9_816 nanoseconds. - Weight::from_ref_time(4_361_319 as u64) - // Standard Error: 13 - .saturating_add(Weight::from_ref_time(1_893 as u64).saturating_mul(s as u64)) + // Minimum execution time: 11_047 nanoseconds. + Weight::from_ref_time(8_068_271) + // Standard Error: 12 + .saturating_add(Weight::from_ref_time(1_983).saturating_mul(s.into())) } // Storage: Ump NeedsDispatch (r:1 w:1) // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) // Storage: Ump RelayDispatchQueues (r:0 w:1) // Storage: Ump RelayDispatchQueueSize (r:0 w:1) fn clean_ump_after_outgoing() -> Weight { - // Minimum execution time: 8_725 nanoseconds. - Weight::from_ref_time(9_100_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 9_837 nanoseconds. + Weight::from_ref_time(10_134_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Ump Overweight (r:1 w:1) fn service_overweight() -> Weight { - // Minimum execution time: 24_444 nanoseconds. - Weight::from_ref_time(25_044_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_666 nanoseconds. + Weight::from_ref_time(27_499_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/test-runtime/Cargo.toml b/runtime/test-runtime/Cargo.toml index c787a5347619..b1a003647c48 100644 --- a/runtime/test-runtime/Cargo.toml +++ b/runtime/test-runtime/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "polkadot-test-runtime" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" build = "build.rs" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } @@ -15,44 +15,44 @@ serde = { version = "1.0.137", default-features = false } serde_derive = { version = "1.0.117", optional = true } smallvec = "1.8.0" -authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, package = "sp-beefy" , branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking-reward-curve = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-system = {git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking-reward-curve = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-system = {git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } test-runtime-constants = { package = "test-runtime-constants", path = "./constants", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false } primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false } @@ -66,12 +66,12 @@ xcm = { path = "../../xcm", default-features = false } [dev-dependencies] hex-literal = "0.3.4" tiny-keccak = { version = "2.0.2", features = ["keccak"] } -keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } serde_json = "1.0.81" [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/runtime/test-runtime/constants/Cargo.toml b/runtime/test-runtime/constants/Cargo.toml index deaec1dd62fe..bdc58b6ab32f 100644 --- a/runtime/test-runtime/constants/Cargo.toml +++ b/runtime/test-runtime/constants/Cargo.toml @@ -1,18 +1,18 @@ [package] name = "test-runtime-constants" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] smallvec = "1.8.0" -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } primitives = { package = "polkadot-primitives", path = "../../../primitives", default-features = false } runtime-common = { package = "polkadot-runtime-common", path = "../../common", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-weights = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/runtime/test-runtime/constants/src/weights/block_weights.rs b/runtime/test-runtime/constants/src/weights/block_weights.rs index c004307336d9..ea8a341b58bb 100644 --- a/runtime/test-runtime/constants/src/weights/block_weights.rs +++ b/runtime/test-runtime/constants/src/weights/block_weights.rs @@ -23,7 +23,8 @@ pub mod constants { parameter_types! { /// Importing a block with 0 Extrinsics. - pub const BlockExecutionWeight: Weight = constants::WEIGHT_PER_NANOS.saturating_mul(5_000_000); + pub const BlockExecutionWeight: Weight = + Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000)); } #[cfg(test)] @@ -39,12 +40,12 @@ pub mod constants { // At least 100 µs. assert!( - w.ref_time() >= 100u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 100 µs." ); // At most 50 ms. assert!( - w.ref_time() <= 50u64 * constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms." ); } diff --git a/runtime/test-runtime/constants/src/weights/extrinsic_weights.rs b/runtime/test-runtime/constants/src/weights/extrinsic_weights.rs index 3ce6b73d5844..0512efb60e2a 100644 --- a/runtime/test-runtime/constants/src/weights/extrinsic_weights.rs +++ b/runtime/test-runtime/constants/src/weights/extrinsic_weights.rs @@ -23,7 +23,8 @@ pub mod constants { parameter_types! { /// Executing a NO-OP `System::remarks` Extrinsic. - pub const ExtrinsicBaseWeight: Weight = constants::WEIGHT_PER_NANOS.saturating_mul(125_000); + pub const ExtrinsicBaseWeight: Weight = + Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000)); } #[cfg(test)] @@ -39,12 +40,12 @@ pub mod constants { // At least 10 µs. assert!( - w.ref_time() >= 10u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs." ); // At most 1 ms. assert!( - w.ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms." ); } diff --git a/runtime/test-runtime/constants/src/weights/paritydb_weights.rs b/runtime/test-runtime/constants/src/weights/paritydb_weights.rs index dca7d348310c..4338d928d807 100644 --- a/runtime/test-runtime/constants/src/weights/paritydb_weights.rs +++ b/runtime/test-runtime/constants/src/weights/paritydb_weights.rs @@ -25,8 +25,8 @@ pub mod constants { /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights /// are available for brave runtime engineers who may want to try this out as default. pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 8_000 * constants::WEIGHT_PER_NANOS.ref_time(), - write: 50_000 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 8_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 50_000 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -42,20 +42,20 @@ pub mod constants { fn sane() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/test-runtime/constants/src/weights/rocksdb_weights.rs b/runtime/test-runtime/constants/src/weights/rocksdb_weights.rs index 87867ebfe177..1d115d963fac 100644 --- a/runtime/test-runtime/constants/src/weights/rocksdb_weights.rs +++ b/runtime/test-runtime/constants/src/weights/rocksdb_weights.rs @@ -25,8 +25,8 @@ pub mod constants { /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout /// the runtime. pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 25_000 * constants::WEIGHT_PER_NANOS.ref_time(), - write: 100_000 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 25_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 100_000 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -42,20 +42,20 @@ pub mod constants { fn sane() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/test-runtime/src/lib.rs b/runtime/test-runtime/src/lib.rs index 7fba0e20d9fe..a30d4d350715 100644 --- a/runtime/test-runtime/src/lib.rs +++ b/runtime/test-runtime/src/lib.rs @@ -319,6 +319,9 @@ parameter_types! { pub storage MaxNominatorRewardedPerValidator: u32 = 64; pub storage OffendingValidatorsThreshold: Perbill = Perbill::from_percent(17); pub const MaxAuthorities: u32 = 100_000; + pub const OnChainMaxWinners: u32 = u32::MAX; + pub const MaxElectingVoters: u32 = u32::MAX; + pub const MaxElectableTargets: u16 = u16::MAX; } pub struct OnChainSeqPhragmen; @@ -327,6 +330,9 @@ impl onchain::Config for OnChainSeqPhragmen { type Solver = SequentialPhragmen; type DataProvider = Staking; type WeightInfo = (); + type MaxWinners = OnChainMaxWinners; + type VotersBound = MaxElectingVoters; + type TargetsBound = MaxElectableTargets; } impl pallet_staking::Config for Runtime { @@ -349,8 +355,8 @@ impl pallet_staking::Config for Runtime { type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; - type ElectionProvider = onchain::UnboundedExecution; - type GenesisElectionProvider = onchain::UnboundedExecution; + type ElectionProvider = onchain::OnChainExecution; + type GenesisElectionProvider = onchain::OnChainExecution; // Use the nominator map to iter voter AND no-ops for all SortedListProvider hooks. The migration // to bags-list is a no-op, but the storage version will be updated. type VoterList = pallet_staking::UseNominatorsAndValidatorsMap; @@ -738,6 +744,7 @@ pub type SignedExtra = ( /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -920,53 +927,31 @@ sp_api::impl_runtime_apis! { } impl mmr::MmrApi for Runtime { - fn generate_proof(_block_number: BlockNumber) - -> Result<(mmr::EncodableOpaqueLeaf, mmr::Proof), mmr::Error> - { - Err(mmr::Error::PalletNotIncluded) - } - - fn verify_proof(_leaf: mmr::EncodableOpaqueLeaf, _proof: mmr::Proof) - -> Result<(), mmr::Error> - { - Err(mmr::Error::PalletNotIncluded) - } - - fn verify_proof_stateless( - _root: Hash, - _leaf: mmr::EncodableOpaqueLeaf, - _proof: mmr::Proof - ) -> Result<(), mmr::Error> { - Err(mmr::Error::PalletNotIncluded) - } - fn mmr_root() -> Result { Err(mmr::Error::PalletNotIncluded) } - fn generate_batch_proof(_block_numbers: Vec) - -> Result<(Vec, mmr::BatchProof), mmr::Error> - { + fn mmr_leaf_count() -> Result { Err(mmr::Error::PalletNotIncluded) } - fn generate_historical_batch_proof( + fn generate_proof( _block_numbers: Vec, - _best_known_block_number: BlockNumber, - ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { + _best_known_block_number: Option, + ) -> Result<(Vec, mmr::Proof), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_batch_proof(_leaves: Vec, _proof: mmr::BatchProof) + fn verify_proof(_leaves: Vec, _proof: mmr::Proof) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_batch_proof_stateless( + fn verify_proof_stateless( _root: Hash, _leaves: Vec, - _proof: mmr::BatchProof + _proof: mmr::Proof ) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } diff --git a/runtime/westend/Cargo.toml b/runtime/westend/Cargo.toml index f43e22249913..d803c992b12f 100644 --- a/runtime/westend/Cargo.toml +++ b/runtime/westend/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "westend-runtime" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" build = "build.rs" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] } @@ -15,74 +15,74 @@ serde = { version = "1.0.137", default-features = false } serde_derive = { version = "1.0.117", optional = true } smallvec = "1.8.0" -authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-npos-elections = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", default-features = false, package = "sp-beefy" , branch = "polkadot-v0.9.36" } +inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-std = { package = "sp-std", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-npos-elections = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } -frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +frame-election-provider-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } westend-runtime-constants = { package = "westend-runtime-constants", path = "./constants", default-features = false } -pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-bags-list = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-elections-phragmen = { package = "pallet-elections-phragmen", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-fast-unstake = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-identity = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-im-online = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-nomination-pools = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-recovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-society = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-staking-reward-curve = { package = "pallet-staking-reward-curve", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-babe = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-bags-list = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-elections-phragmen = { package = "pallet-elections-phragmen", git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-fast-unstake = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-identity = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-im-online = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-indices = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-nomination-pools = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-offences = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-recovery = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-society = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-staking-reward-curve = { package = "pallet-staking-reward-curve", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-nomination-pools-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } pallet-xcm = { path = "../../xcm/pallet-xcm", default-features = false } pallet-xcm-benchmarks = { path = "../../xcm/pallet-xcm-benchmarks", default-features = false, optional = true } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-election-provider-support-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-nomination-pools-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-offences-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } -pallet-session-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-election-provider-support-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-nomination-pools-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-offences-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } +pallet-session-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } hex-literal = { version = "0.3.4", optional = true } runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false } @@ -97,15 +97,15 @@ xcm-builder = { package = "xcm-builder", path = "../../xcm/xcm-builder", default [dev-dependencies] hex-literal = "0.3.4" tiny-keccak = { version = "2.0.2", features = ["keccak"] } -keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } serde_json = "1.0.81" -remote-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -tokio = { version = "1.19.2", features = ["macros"] } -sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +remote-externalities = { git = "https://github.com/paritytech/substrate", package = "frame-remote-externalities" , branch = "polkadot-v0.9.36" } +tokio = { version = "1.22.0", features = ["macros"] } +sp-tracing = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/runtime/westend/constants/Cargo.toml b/runtime/westend/constants/Cargo.toml index 93a3ca44591f..7ea496ef10f9 100644 --- a/runtime/westend/constants/Cargo.toml +++ b/runtime/westend/constants/Cargo.toml @@ -1,18 +1,18 @@ [package] name = "westend-runtime-constants" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] smallvec = "1.8.0" -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } primitives = { package = "polkadot-primitives", path = "../../../primitives", default-features = false } runtime-common = { package = "polkadot-runtime-common", path = "../../common", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-weights = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/runtime/westend/constants/src/weights/block_weights.rs b/runtime/westend/constants/src/weights/block_weights.rs index 9ff4e96f0c48..0aa67d7586bd 100644 --- a/runtime/westend/constants/src/weights/block_weights.rs +++ b/runtime/westend/constants/src/weights/block_weights.rs @@ -14,7 +14,7 @@ // 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: 2022-10-25 (Y/M/D) +//! DATE: 2022-12-15 (Y/M/D) //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `block`, LONG-NAME: `BlockExecution`, RUNTIME: `Development` @@ -35,23 +35,24 @@ // --header=./file_header.txt use sp_core::parameter_types; -use sp_weights::{constants::WEIGHT_PER_NANOS, Weight}; +use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; parameter_types! { /// Time to execute an empty block. /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 4_898_859, 5_130_799 - /// Average: 5_000_060 - /// Median: 5_005_375 - /// Std-Dev: 60863.28 + /// Min, Max: 5_099_998, 5_275_118 + /// Average: 5_172_036 + /// Median: 5_172_275 + /// Std-Dev: 50998.86 /// /// Percentiles nanoseconds: - /// 99th: 5_119_528 - /// 95th: 5_095_268 - /// 75th: 5_040_113 - pub const BlockExecutionWeight: Weight = WEIGHT_PER_NANOS.saturating_mul(5_000_060); + /// 99th: 5_273_226 + /// 95th: 5_253_153 + /// 75th: 5_209_228 + pub const BlockExecutionWeight: Weight = + Weight::from_ref_time(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_172_036)); } #[cfg(test)] @@ -67,12 +68,12 @@ mod test_weights { // At least 100 µs. assert!( - w.ref_time() >= 100u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 100 µs." ); // At most 50 ms. assert!( - w.ref_time() <= 50u64 * constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms." ); } diff --git a/runtime/westend/constants/src/weights/extrinsic_weights.rs b/runtime/westend/constants/src/weights/extrinsic_weights.rs index f52e2961660e..598c30a689d1 100644 --- a/runtime/westend/constants/src/weights/extrinsic_weights.rs +++ b/runtime/westend/constants/src/weights/extrinsic_weights.rs @@ -14,7 +14,7 @@ // 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: 2022-10-25 (Y/M/D) +//! DATE: 2022-12-15 (Y/M/D) //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! //! SHORT-NAME: `extrinsic`, LONG-NAME: `ExtrinsicBase`, RUNTIME: `Development` @@ -35,23 +35,24 @@ // --header=./file_header.txt use sp_core::parameter_types; -use sp_weights::{constants::WEIGHT_PER_NANOS, Weight}; +use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight}; parameter_types! { /// Time to execute a NO-OP extrinsic, for example `System::remark`. /// Calculated by multiplying the *Average* with `1.0` and adding `0`. /// /// Stats nanoseconds: - /// Min, Max: 87_511, 89_510 - /// Average: 87_998 - /// Median: 87_963 - /// Std-Dev: 317.63 + /// Min, Max: 89_128, 91_461 + /// Average: 89_646 + /// Median: 89_595 + /// Std-Dev: 356.22 /// /// Percentiles nanoseconds: - /// 99th: 89_279 - /// 95th: 88_456 - /// 75th: 88_052 - pub const ExtrinsicBaseWeight: Weight = WEIGHT_PER_NANOS.saturating_mul(87_998); + /// 99th: 91_146 + /// 95th: 90_284 + /// 75th: 89_668 + pub const ExtrinsicBaseWeight: Weight = + Weight::from_ref_time(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(89_646)); } #[cfg(test)] @@ -67,12 +68,12 @@ mod test_weights { // At least 10 µs. assert!( - w.ref_time() >= 10u64 * constants::WEIGHT_PER_MICROS.ref_time(), + w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs." ); // At most 1 ms. assert!( - w.ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms." ); } diff --git a/runtime/westend/constants/src/weights/paritydb_weights.rs b/runtime/westend/constants/src/weights/paritydb_weights.rs index dca7d348310c..4338d928d807 100644 --- a/runtime/westend/constants/src/weights/paritydb_weights.rs +++ b/runtime/westend/constants/src/weights/paritydb_weights.rs @@ -25,8 +25,8 @@ pub mod constants { /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights /// are available for brave runtime engineers who may want to try this out as default. pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 8_000 * constants::WEIGHT_PER_NANOS.ref_time(), - write: 50_000 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 8_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 50_000 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -42,20 +42,20 @@ pub mod constants { fn sane() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/westend/constants/src/weights/rocksdb_weights.rs b/runtime/westend/constants/src/weights/rocksdb_weights.rs index 87867ebfe177..1d115d963fac 100644 --- a/runtime/westend/constants/src/weights/rocksdb_weights.rs +++ b/runtime/westend/constants/src/weights/rocksdb_weights.rs @@ -25,8 +25,8 @@ pub mod constants { /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout /// the runtime. pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 25_000 * constants::WEIGHT_PER_NANOS.ref_time(), - write: 100_000 * constants::WEIGHT_PER_NANOS.ref_time(), + read: 25_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 100_000 * constants::WEIGHT_REF_TIME_PER_NANOS, }; } @@ -42,20 +42,20 @@ pub mod constants { fn sane() { // At least 1 µs. assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Read weight should be at least 1 µs." ); assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_PER_MICROS.ref_time(), + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, "Write weight should be at least 1 µs." ); // At most 1 ms. assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Read weight should be at most 1 ms." ); assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_PER_MILLIS.ref_time(), + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Write weight should be at most 1 ms." ); } diff --git a/runtime/westend/src/lib.rs b/runtime/westend/src/lib.rs index 3ee7a65584a3..a56a01f45704 100644 --- a/runtime/westend/src/lib.rs +++ b/runtime/westend/src/lib.rs @@ -109,13 +109,13 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("westend"), impl_name: create_runtime_str!("parity-westend"), authoring_version: 2, - spec_version: 9310, + spec_version: 9360, impl_version: 0, #[cfg(not(feature = "disable-runtime-api"))] apis: RUNTIME_API_VERSIONS, #[cfg(feature = "disable-runtime-api")] apis: sp_version::create_apis_vec![[]], - transaction_version: 14, + transaction_version: 17, state_version: 0, }; @@ -366,6 +366,9 @@ parameter_types! { /// ... and all of the validators as electable targets. Whilst this is the case, we cannot and /// shall not increase the size of the validator intentions. pub const MaxElectableTargets: u16 = u16::MAX; + // Maximum winners that can be chosen as active validators + pub const MaxActiveValidators: u32 = 1000; + } frame_election_provider_support::generate_solution_type!( @@ -384,6 +387,9 @@ impl onchain::Config for OnChainSeqPhragmen { type Solver = SequentialPhragmen; type DataProvider = Staking; type WeightInfo = weights::frame_election_provider_support::WeightInfo; + type MaxWinners = MaxActiveValidators; + type VotersBound = MaxElectingVoters; + type TargetsBound = MaxElectableTargets; } impl pallet_election_provider_multi_phase::MinerConfig for Runtime { @@ -431,10 +437,15 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type MinerTxPriority = NposSolutionPriority; type DataProvider = Staking; #[cfg(any(feature = "fast-runtime", feature = "runtime-benchmarks"))] - type Fallback = onchain::UnboundedExecution; + type Fallback = onchain::OnChainExecution; #[cfg(not(any(feature = "fast-runtime", feature = "runtime-benchmarks")))] - type Fallback = pallet_election_provider_multi_phase::NoFallback; - type GovernanceFallback = onchain::UnboundedExecution; + type Fallback = frame_election_provider_support::NoElection<( + AccountId, + BlockNumber, + Staking, + MaxActiveValidators, + )>; + type GovernanceFallback = onchain::OnChainExecution; type Solver = SequentialPhragmen< AccountId, pallet_election_provider_multi_phase::SolutionAccuracyOf, @@ -445,6 +456,7 @@ impl pallet_election_provider_multi_phase::Config for Runtime { type WeightInfo = weights::pallet_election_provider_multi_phase::WeightInfo; type MaxElectingVoters = MaxElectingVoters; type MaxElectableTargets = MaxElectableTargets; + type MaxWinners = MaxActiveValidators; } parameter_types! { @@ -505,7 +517,7 @@ impl pallet_staking::Config for Runtime { type OffendingValidatorsThreshold = OffendingValidatorsThreshold; type NextNewSession = Session; type ElectionProvider = ElectionProviderMultiPhase; - type GenesisElectionProvider = onchain::UnboundedExecution; + type GenesisElectionProvider = onchain::OnChainExecution; type VoterList = VoterList; type TargetList = UseValidatorsMap; type MaxUnlockingChunks = frame_support::traits::ConstU32<32>; @@ -517,10 +529,12 @@ impl pallet_staking::Config for Runtime { impl pallet_fast_unstake::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type DepositCurrency = Balances; + type Currency = Balances; + type BatchSize = frame_support::traits::ConstU32<64>; type Deposit = frame_support::traits::ConstU128<{ UNITS }>; type ControlOrigin = EnsureRoot; type WeightInfo = weights::pallet_fast_unstake::WeightInfo; + type Staking = Staking; } parameter_types! { @@ -679,7 +693,7 @@ parameter_types! { pub const DepositBase: Balance = deposit(1, 88); // Additional storage item size of 32 bytes. pub const DepositFactor: Balance = deposit(0, 32); - pub const MaxSignatories: u16 = 100; + pub const MaxSignatories: u32 = 100; } impl pallet_multisig::Config for Runtime { @@ -1060,11 +1074,10 @@ impl pallet_nomination_pools::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = weights::pallet_nomination_pools::WeightInfo; type Currency = Balances; - type CurrencyBalance = Balance; type RewardCounter = FixedU128; type BalanceToU256 = BalanceToU256; type U256ToBalance = U256ToBalance; - type StakingInterface = Staking; + type Staking = Staking; type PostUnbondingPoolsWindow = ConstU32<4>; type MaxMetadataLen = ConstU32<256>; // we use the same number of allowed unlocking chunks as with staking. @@ -1199,6 +1212,8 @@ impl Get<&'static str> for StakingMigrationV11OldPallet { } } +pub type Migrations = (); + /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; @@ -1209,14 +1224,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - ( - // "Bound uses of call" - pallet_preimage::migration::v1::Migration, - pallet_scheduler::migration::v3::MigrateToV4, - pallet_multisig::migrations::v1::MigrateToV1, - // "Properly migrate weights to v2" - parachains_configuration::migration::v3::MigrateToV3, - ), + Migrations, >; /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; @@ -1443,58 +1451,32 @@ sp_api::impl_runtime_apis! { } impl mmr::MmrApi for Runtime { - fn generate_proof(_block_number: BlockNumber) - -> Result<(mmr::EncodableOpaqueLeaf, mmr::Proof), mmr::Error> - { - - Err(mmr::Error::PalletNotIncluded) - } - - fn verify_proof(_leaf: mmr::EncodableOpaqueLeaf, _proof: mmr::Proof) - -> Result<(), mmr::Error> - { - - Err(mmr::Error::PalletNotIncluded) - } - - fn verify_proof_stateless( - _root: Hash, - _leaf: mmr::EncodableOpaqueLeaf, - _proof: mmr::Proof - ) -> Result<(), mmr::Error> { - - Err(mmr::Error::PalletNotIncluded) - } - fn mmr_root() -> Result { - Err(mmr::Error::PalletNotIncluded) } - fn generate_batch_proof(_block_numbers: Vec) - -> Result<(Vec, mmr::BatchProof), mmr::Error> - { + fn mmr_leaf_count() -> Result { Err(mmr::Error::PalletNotIncluded) } - fn generate_historical_batch_proof( + fn generate_proof( _block_numbers: Vec, - _best_known_block_number: BlockNumber, - ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { + _best_known_block_number: Option, + ) -> Result<(Vec, mmr::Proof), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_batch_proof(_leaves: Vec, _proof: mmr::BatchProof) + fn verify_proof(_leaves: Vec, _proof: mmr::Proof) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) } - fn verify_batch_proof_stateless( + fn verify_proof_stateless( _root: Hash, _leaves: Vec, - _proof: mmr::BatchProof + _proof: mmr::Proof ) -> Result<(), mmr::Error> { Err(mmr::Error::PalletNotIncluded) @@ -1645,21 +1627,21 @@ sp_api::impl_runtime_apis! { #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { - fn on_runtime_upgrade() -> (Weight, Weight) { + fn on_runtime_upgrade(checks: bool) -> (Weight, Weight) { log::info!("try-runtime::on_runtime_upgrade westend."); - let weight = Executive::try_runtime_upgrade().unwrap(); + let weight = Executive::try_runtime_upgrade(checks).unwrap(); (weight, BlockWeights::get().max_block) } - fn execute_block(block: Block, state_root_check: bool, select: frame_try_runtime::TryStateSelect) -> Weight { - log::info!( - target: "runtime::westend", "try-runtime: executing block #{} ({:?}) / root checks: {:?} / sanity-checks: {:?}", - block.header.number, - block.header.hash(), - state_root_check, - select, - ); - Executive::try_execute_block(block, state_root_check, select).expect("try_execute_block failed") + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect, + ) -> Weight { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. + Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() } } @@ -1847,6 +1829,6 @@ mod remote_tests { .build() .await .unwrap(); - ext.execute_with(|| Runtime::on_runtime_upgrade()); + ext.execute_with(|| Runtime::on_runtime_upgrade(true)); } } diff --git a/runtime/westend/src/weights/frame_election_provider_support.rs b/runtime/westend/src/weights/frame_election_provider_support.rs index b202638d2817..686f0110530e 100644 --- a/runtime/westend/src/weights/frame_election_provider_support.rs +++ b/runtime/westend/src/weights/frame_election_provider_support.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_election_provider_support` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -48,22 +48,22 @@ impl frame_election_provider_support::WeightInfo for We /// The range of component `t` is `[500, 1000]`. /// The range of component `d` is `[5, 16]`. fn phragmen(v: u32, _t: u32, d: u32, ) -> Weight { - // Minimum execution time: 5_449_895 nanoseconds. - Weight::from_ref_time(5_493_777_000 as u64) - // Standard Error: 137_519 - .saturating_add(Weight::from_ref_time(5_601_334 as u64).saturating_mul(v as u64)) - // Standard Error: 14_059_549 - .saturating_add(Weight::from_ref_time(1_555_417_760 as u64).saturating_mul(d as u64)) + // Minimum execution time: 5_723_844 nanoseconds. + Weight::from_ref_time(5_782_575_000) + // Standard Error: 136_881 + .saturating_add(Weight::from_ref_time(5_669_281).saturating_mul(v.into())) + // Standard Error: 13_994_291 + .saturating_add(Weight::from_ref_time(1_533_934_753).saturating_mul(d.into())) } /// The range of component `v` is `[1000, 2000]`. /// The range of component `t` is `[500, 1000]`. /// The range of component `d` is `[5, 16]`. fn phragmms(v: u32, _t: u32, d: u32, ) -> Weight { - // Minimum execution time: 4_267_232 nanoseconds. - Weight::from_ref_time(4_311_499_000 as u64) - // Standard Error: 146_807 - .saturating_add(Weight::from_ref_time(5_470_097 as u64).saturating_mul(v as u64)) - // Standard Error: 15_009_027 - .saturating_add(Weight::from_ref_time(1_764_707_366 as u64).saturating_mul(d as u64)) + // Minimum execution time: 4_415_498 nanoseconds. + Weight::from_ref_time(4_453_849_000) + // Standard Error: 145_262 + .saturating_add(Weight::from_ref_time(5_507_786).saturating_mul(v.into())) + // Standard Error: 14_851_158 + .saturating_add(Weight::from_ref_time(1_750_852_788).saturating_mul(d.into())) } } diff --git a/runtime/westend/src/weights/frame_system.rs b/runtime/westend/src/weights/frame_system.rs index 039d8c6ccd56..1214bc3e5f37 100644 --- a/runtime/westend/src/weights/frame_system.rs +++ b/runtime/westend/src/weights/frame_system.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `frame_system` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -46,51 +46,51 @@ pub struct WeightInfo(PhantomData); impl frame_system::WeightInfo for WeightInfo { /// The range of component `b` is `[0, 3932160]`. fn remark(b: u32, ) -> Weight { - // Minimum execution time: 3_353 nanoseconds. - Weight::from_ref_time(3_505_000 as u64) + // Minimum execution time: 3_840 nanoseconds. + Weight::from_ref_time(3_901_000) // Standard Error: 0 - .saturating_add(Weight::from_ref_time(412 as u64).saturating_mul(b as u64)) + .saturating_add(Weight::from_ref_time(512).saturating_mul(b.into())) } /// The range of component `b` is `[0, 3932160]`. fn remark_with_event(b: u32, ) -> Weight { - // Minimum execution time: 12_086 nanoseconds. - Weight::from_ref_time(12_284_000 as u64) + // Minimum execution time: 13_591 nanoseconds. + Weight::from_ref_time(13_785_000) // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_730 as u64).saturating_mul(b as u64)) + .saturating_add(Weight::from_ref_time(1_871).saturating_mul(b.into())) } // Storage: System Digest (r:1 w:1) // Storage: unknown [0x3a686561707061676573] (r:0 w:1) fn set_heap_pages() -> Weight { - // Minimum execution time: 7_570 nanoseconds. - Weight::from_ref_time(7_711_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 8_638 nanoseconds. + Weight::from_ref_time(8_960_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn set_storage(i: u32, ) -> Weight { - // Minimum execution time: 3_656 nanoseconds. - Weight::from_ref_time(3_725_000 as u64) - // Standard Error: 2_119 - .saturating_add(Weight::from_ref_time(602_695 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 4_118 nanoseconds. + Weight::from_ref_time(4_192_000) + // Standard Error: 2_176 + .saturating_add(Weight::from_ref_time(630_389).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `i` is `[0, 1000]`. fn kill_storage(i: u32, ) -> Weight { - // Minimum execution time: 3_631 nanoseconds. - Weight::from_ref_time(3_661_000 as u64) - // Standard Error: 1_080 - .saturating_add(Weight::from_ref_time(435_664 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + // Minimum execution time: 4_220 nanoseconds. + Weight::from_ref_time(4_278_000) + // Standard Error: 962 + .saturating_add(Weight::from_ref_time(451_817).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(i.into()))) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `p` is `[0, 1000]`. fn kill_prefix(p: u32, ) -> Weight { - // Minimum execution time: 5_220 nanoseconds. - Weight::from_ref_time(5_369_000 as u64) - // Standard Error: 1_204 - .saturating_add(Weight::from_ref_time(933_358 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 6_118 nanoseconds. + Weight::from_ref_time(6_226_000) + // Standard Error: 1_231 + .saturating_add(Weight::from_ref_time(969_516).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(p.into()))) } } diff --git a/runtime/westend/src/weights/pallet_bags_list.rs b/runtime/westend/src/weights/pallet_bags_list.rs index dbea6151cd11..4c8a63ad0701 100644 --- a/runtime/westend/src/weights/pallet_bags_list.rs +++ b/runtime/westend/src/weights/pallet_bags_list.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_bags_list` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -49,20 +49,20 @@ impl pallet_bags_list::WeightInfo for WeightInfo { // Storage: VoterList ListNodes (r:4 w:4) // Storage: VoterList ListBags (r:1 w:1) fn rebag_non_terminal() -> Weight { - // Minimum execution time: 61_542 nanoseconds. - Weight::from_ref_time(62_218_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 63_995 nanoseconds. + Weight::from_ref_time(64_733_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn rebag_terminal() -> Weight { - // Minimum execution time: 60_842 nanoseconds. - Weight::from_ref_time(61_595_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 63_061 nanoseconds. + Weight::from_ref_time(63_853_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: VoterList ListNodes (r:4 w:4) // Storage: Staking Bonded (r:2 w:0) @@ -70,9 +70,9 @@ impl pallet_bags_list::WeightInfo for WeightInfo { // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: VoterList ListBags (r:1 w:1) fn put_in_front_of() -> Weight { - // Minimum execution time: 60_377 nanoseconds. - Weight::from_ref_time(61_315_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 62_678 nanoseconds. + Weight::from_ref_time(63_288_000) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(6)) } } diff --git a/runtime/westend/src/weights/pallet_balances.rs b/runtime/westend/src/weights/pallet_balances.rs index c86f678b4573..e3174bdf7820 100644 --- a/runtime/westend/src/weights/pallet_balances.rs +++ b/runtime/westend/src/weights/pallet_balances.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_balances` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -46,51 +46,51 @@ pub struct WeightInfo(PhantomData); impl pallet_balances::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - // Minimum execution time: 39_828 nanoseconds. - Weight::from_ref_time(40_284_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 41_367 nanoseconds. + Weight::from_ref_time(41_776_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn transfer_keep_alive() -> Weight { - // Minimum execution time: 29_216 nanoseconds. - Weight::from_ref_time(29_760_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 31_378 nanoseconds. + Weight::from_ref_time(31_781_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn set_balance_creating() -> Weight { - // Minimum execution time: 22_724 nanoseconds. - Weight::from_ref_time(23_242_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 24_022 nanoseconds. + Weight::from_ref_time(24_762_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn set_balance_killing() -> Weight { - // Minimum execution time: 25_275 nanoseconds. - Weight::from_ref_time(25_951_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_478 nanoseconds. + Weight::from_ref_time(27_064_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:2 w:2) fn force_transfer() -> Weight { - // Minimum execution time: 38_922 nanoseconds. - Weight::from_ref_time(39_926_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 41_384 nanoseconds. + Weight::from_ref_time(42_178_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: System Account (r:1 w:1) fn transfer_all() -> Weight { - // Minimum execution time: 34_624 nanoseconds. - Weight::from_ref_time(35_268_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 36_952 nanoseconds. + Weight::from_ref_time(37_568_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) fn force_unreserve() -> Weight { - // Minimum execution time: 19_457 nanoseconds. - Weight::from_ref_time(19_975_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 21_210 nanoseconds. + Weight::from_ref_time(21_647_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/pallet_election_provider_multi_phase.rs b/runtime/westend/src/weights/pallet_election_provider_multi_phase.rs index 4feebaedbcc6..3564cd600b41 100644 --- a/runtime/westend/src/weights/pallet_election_provider_multi_phase.rs +++ b/runtime/westend/src/weights/pallet_election_provider_multi_phase.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_election_provider_multi_phase` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -53,40 +53,40 @@ impl pallet_election_provider_multi_phase::WeightInfo f // Storage: Staking ForceEra (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) fn on_initialize_nothing() -> Weight { - // Minimum execution time: 13_872 nanoseconds. - Weight::from_ref_time(14_158_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) + // Minimum execution time: 16_349 nanoseconds. + Weight::from_ref_time(16_709_000) + .saturating_add(T::DbWeight::get().reads(8)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_signed() -> Weight { - // Minimum execution time: 13_293 nanoseconds. - Weight::from_ref_time(13_707_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 14_031 nanoseconds. + Weight::from_ref_time(14_452_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:0 w:1) fn on_initialize_open_unsigned() -> Weight { - // Minimum execution time: 12_955 nanoseconds. - Weight::from_ref_time(13_378_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 13_861 nanoseconds. + Weight::from_ref_time(14_243_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: System Account (r:1 w:1) // Storage: ElectionProviderMultiPhase QueuedSolution (r:0 w:1) fn finalize_signed_phase_accept_solution() -> Weight { - // Minimum execution time: 28_501 nanoseconds. - Weight::from_ref_time(29_121_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 30_255 nanoseconds. + Weight::from_ref_time(30_929_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: System Account (r:1 w:1) fn finalize_signed_phase_reject_solution() -> Weight { - // Minimum execution time: 22_012 nanoseconds. - Weight::from_ref_time(22_395_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 23_759 nanoseconds. + Weight::from_ref_time(24_256_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ElectionProviderMultiPhase SnapshotMetadata (r:0 w:1) // Storage: ElectionProviderMultiPhase DesiredTargets (r:0 w:1) @@ -94,11 +94,11 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// 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 { - // Minimum execution time: 417_221 nanoseconds. - Weight::from_ref_time(427_368_000 as u64) - // Standard Error: 2_342 - .saturating_add(Weight::from_ref_time(264_068 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 435_167 nanoseconds. + Weight::from_ref_time(444_470_000) + // Standard Error: 2_460 + .saturating_add(Weight::from_ref_time(266_808).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: ElectionProviderMultiPhase SignedSubmissionIndices (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) @@ -113,14 +113,14 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn elect_queued(a: u32, d: u32, ) -> Weight { - // Minimum execution time: 272_735 nanoseconds. - Weight::from_ref_time(101_494_679 as u64) - // Standard Error: 6_085 - .saturating_add(Weight::from_ref_time(306_319 as u64).saturating_mul(a as u64)) - // Standard Error: 9_122 - .saturating_add(Weight::from_ref_time(120_469 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 280_515 nanoseconds. + Weight::from_ref_time(100_927_078) + // Standard Error: 5_359 + .saturating_add(Weight::from_ref_time(332_802).saturating_mul(a.into())) + // Standard Error: 8_033 + .saturating_add(Weight::from_ref_time(77_533).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(9)) } // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: ElectionProviderMultiPhase SnapshotMetadata (r:1 w:0) @@ -129,10 +129,10 @@ impl pallet_election_provider_multi_phase::WeightInfo f // Storage: ElectionProviderMultiPhase SignedSubmissionNextIndex (r:1 w:1) // Storage: ElectionProviderMultiPhase SignedSubmissionsMap (r:0 w:1) fn submit() -> Weight { - // Minimum execution time: 57_464 nanoseconds. - Weight::from_ref_time(58_191_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 59_634 nanoseconds. + Weight::from_ref_time(60_784_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: ElectionProviderMultiPhase Round (r:1 w:0) @@ -146,14 +146,14 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn submit_unsigned(v: u32, _t: u32, a: u32, _d: u32, ) -> Weight { - // Minimum execution time: 4_705_189 nanoseconds. - Weight::from_ref_time(4_737_998_000 as u64) - // Standard Error: 14_252 - .saturating_add(Weight::from_ref_time(112_874 as u64).saturating_mul(v as u64)) - // Standard Error: 42_234 - .saturating_add(Weight::from_ref_time(4_421_938 as u64).saturating_mul(a as u64)) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_773_587 nanoseconds. + Weight::from_ref_time(4_806_306_000) + // Standard Error: 14_744 + .saturating_add(Weight::from_ref_time(103_020).saturating_mul(v.into())) + // Standard Error: 43_694 + .saturating_add(Weight::from_ref_time(4_578_179).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ElectionProviderMultiPhase Round (r:1 w:0) // Storage: ElectionProviderMultiPhase DesiredTargets (r:1 w:0) @@ -164,12 +164,12 @@ impl pallet_election_provider_multi_phase::WeightInfo f /// The range of component `a` is `[500, 800]`. /// The range of component `d` is `[200, 400]`. fn feasibility_check(v: u32, _t: u32, a: u32, _d: u32, ) -> Weight { - // Minimum execution time: 3_888_041 nanoseconds. - Weight::from_ref_time(3_911_372_000 as u64) - // Standard Error: 12_374 - .saturating_add(Weight::from_ref_time(216_707 as u64).saturating_mul(v as u64)) - // Standard Error: 36_671 - .saturating_add(Weight::from_ref_time(3_193_380 as u64).saturating_mul(a as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) + // Minimum execution time: 3_967_297 nanoseconds. + Weight::from_ref_time(3_982_750_000) + // Standard Error: 12_214 + .saturating_add(Weight::from_ref_time(204_637).saturating_mul(v.into())) + // Standard Error: 36_195 + .saturating_add(Weight::from_ref_time(3_307_742).saturating_mul(a.into())) + .saturating_add(T::DbWeight::get().reads(4)) } } diff --git a/runtime/westend/src/weights/pallet_fast_unstake.rs b/runtime/westend/src/weights/pallet_fast_unstake.rs index e3e49790c499..fe7818b0144b 100644 --- a/runtime/westend/src/weights/pallet_fast_unstake.rs +++ b/runtime/westend/src/weights/pallet_fast_unstake.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_fast_unstake` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -49,56 +49,57 @@ impl pallet_fast_unstake::WeightInfo for WeightInfo // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking SlashingSpans (r:1 w:0) - // Storage: Staking Bonded (r:1 w:1) - // Storage: Staking Validators (r:1 w:0) - // Storage: Staking Nominators (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: Staking Ledger (r:0 w:1) - // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SlashingSpans (r:64 w:0) + // Storage: Staking Bonded (r:64 w:64) + // Storage: Staking Validators (r:64 w:0) + // Storage: Staking Nominators (r:64 w:0) + // Storage: System Account (r:64 w:64) + // Storage: Balances Locks (r:64 w:64) + // Storage: Staking Ledger (r:0 w:64) + // Storage: Staking Payee (r:0 w:64) fn on_idle_unstake() -> Weight { - // Minimum execution time: 70_324 nanoseconds. - Weight::from_ref_time(71_121_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 2_253_744 nanoseconds. + Weight::from_ref_time(2_294_283_000) + .saturating_add(T::DbWeight::get().reads(389)) + .saturating_add(T::DbWeight::get().writes(321)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking ValidatorCount (r:1 w:0) // Storage: ElectionProviderMultiPhase CurrentPhase (r:1 w:0) // Storage: FastUnstake Head (r:1 w:1) - // Storage: FastUnstake Queue (r:2 w:1) + // Storage: FastUnstake Queue (r:65 w:64) // Storage: FastUnstake CounterForQueue (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking ErasStakers (r:4 w:0) /// The range of component `x` is `[2, 256]`. fn on_idle_check(x: u32, ) -> Weight { - // Minimum execution time: 69_870 nanoseconds. - Weight::from_ref_time(31_444_073 as u64) - // Standard Error: 16_618 - .saturating_add(Weight::from_ref_time(13_785_536 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(x as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 2_379_016 nanoseconds. + Weight::from_ref_time(2_432_780_000) + // Standard Error: 886_744 + .saturating_add(Weight::from_ref_time(832_238_992).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(72)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(66)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: FastUnstake Queue (r:1 w:1) // Storage: FastUnstake Head (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) - // Storage: VoterList ListNodes (r:1 w:1) + // Storage: VoterList ListNodes (r:2 w:2) // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn register_fast_unstake() -> Weight { - // Minimum execution time: 92_222 nanoseconds. - Weight::from_ref_time(93_069_000 as u64) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 129_141 nanoseconds. + Weight::from_ref_time(132_182_000) + .saturating_add(T::DbWeight::get().reads(15)) + .saturating_add(T::DbWeight::get().writes(10)) } // Storage: FastUnstake ErasToCheckPerBlock (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) @@ -106,15 +107,15 @@ impl pallet_fast_unstake::WeightInfo for WeightInfo // Storage: FastUnstake Head (r:1 w:0) // Storage: FastUnstake CounterForQueue (r:1 w:1) fn deregister() -> Weight { - // Minimum execution time: 39_901 nanoseconds. - Weight::from_ref_time(40_412_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 50_908 nanoseconds. + Weight::from_ref_time(52_386_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: FastUnstake ErasToCheckPerBlock (r:0 w:1) fn control() -> Weight { - // Minimum execution time: 4_152 nanoseconds. - Weight::from_ref_time(4_223_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_653 nanoseconds. + Weight::from_ref_time(4_811_000) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/pallet_identity.rs b/runtime/westend/src/weights/pallet_identity.rs index e5f7182439fb..9711f8000b3c 100644 --- a/runtime/westend/src/weights/pallet_identity.rs +++ b/runtime/westend/src/weights/pallet_identity.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_identity` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -47,52 +47,52 @@ impl pallet_identity::WeightInfo for WeightInfo { // Storage: Identity Registrars (r:1 w:1) /// The range of component `r` is `[1, 19]`. fn add_registrar(r: u32, ) -> Weight { - // Minimum execution time: 16_193 nanoseconds. - Weight::from_ref_time(17_760_055 as u64) - // Standard Error: 3_798 - .saturating_add(Weight::from_ref_time(167_468 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 18_131 nanoseconds. + Weight::from_ref_time(19_355_815) + // Standard Error: 3_541 + .saturating_add(Weight::from_ref_time(155_675).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) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn set_identity(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 35_137 nanoseconds. - Weight::from_ref_time(34_360_744 as u64) - // Standard Error: 3_823 - .saturating_add(Weight::from_ref_time(92_219 as u64).saturating_mul(r as u64)) - // Standard Error: 746 - .saturating_add(Weight::from_ref_time(291_632 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 38_599 nanoseconds. + Weight::from_ref_time(36_106_804) + // Standard Error: 6_572 + .saturating_add(Weight::from_ref_time(157_847).saturating_mul(r.into())) + // Standard Error: 1_282 + .saturating_add(Weight::from_ref_time(407_972).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:2 w:2) /// The range of component `s` is `[0, 100]`. fn set_subs_new(s: u32, ) -> Weight { - // Minimum execution time: 10_464 nanoseconds. - Weight::from_ref_time(28_442_904 as u64) - // Standard Error: 4_842 - .saturating_add(Weight::from_ref_time(2_085_306 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 11_145 nanoseconds. + Weight::from_ref_time(30_821_849) + // Standard Error: 5_171 + .saturating_add(Weight::from_ref_time(2_318_309).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()))) } // Storage: Identity IdentityOf (r:1 w:0) // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity SuperOf (r:0 w:2) /// The range of component `p` is `[0, 100]`. fn set_subs_old(p: u32, ) -> Weight { - // Minimum execution time: 10_026 nanoseconds. - Weight::from_ref_time(28_049_091 as u64) - // Standard Error: 4_248 - .saturating_add(Weight::from_ref_time(913_087 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + // Minimum execution time: 11_023 nanoseconds. + Weight::from_ref_time(30_672_202) + // Standard Error: 4_655 + .saturating_add(Weight::from_ref_time(971_190).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) // Storage: Identity IdentityOf (r:1 w:1) @@ -101,88 +101,88 @@ impl pallet_identity::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. /// The range of component `x` is `[0, 100]`. fn clear_identity(r: u32, s: u32, x: u32, ) -> Weight { - // Minimum execution time: 49_412 nanoseconds. - Weight::from_ref_time(36_040_592 as u64) - // Standard Error: 7_291 - .saturating_add(Weight::from_ref_time(84_806 as u64).saturating_mul(r as u64)) - // Standard Error: 1_423 - .saturating_add(Weight::from_ref_time(888_161 as u64).saturating_mul(s as u64)) - // Standard Error: 1_423 - .saturating_add(Weight::from_ref_time(160_244 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 54_602 nanoseconds. + Weight::from_ref_time(38_688_311) + // Standard Error: 4_577 + .saturating_add(Weight::from_ref_time(100_423).saturating_mul(r.into())) + // Standard Error: 893 + .saturating_add(Weight::from_ref_time(937_982).saturating_mul(s.into())) + // Standard Error: 893 + .saturating_add(Weight::from_ref_time(183_903).saturating_mul(x.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) // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn request_judgement(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 37_198 nanoseconds. - Weight::from_ref_time(35_602_420 as u64) - // Standard Error: 6_208 - .saturating_add(Weight::from_ref_time(139_935 as u64).saturating_mul(r as u64)) - // Standard Error: 1_211 - .saturating_add(Weight::from_ref_time(318_552 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 39_987 nanoseconds. + Weight::from_ref_time(39_648_106) + // Standard Error: 11_011 + .saturating_add(Weight::from_ref_time(130_117).saturating_mul(r.into())) + // Standard Error: 2_148 + .saturating_add(Weight::from_ref_time(401_847).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 20]`. /// The range of component `x` is `[0, 100]`. fn cancel_request(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 33_660 nanoseconds. - Weight::from_ref_time(33_265_758 as u64) - // Standard Error: 4_249 - .saturating_add(Weight::from_ref_time(75_193 as u64).saturating_mul(r as u64)) - // Standard Error: 829 - .saturating_add(Weight::from_ref_time(313_336 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 36_290 nanoseconds. + Weight::from_ref_time(35_437_506) + // Standard Error: 4_581 + .saturating_add(Weight::from_ref_time(86_490).saturating_mul(r.into())) + // Standard Error: 893 + .saturating_add(Weight::from_ref_time(416_099).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity Registrars (r:1 w:1) /// The range of component `r` is `[1, 19]`. fn set_fee(r: u32, ) -> Weight { - // Minimum execution time: 8_557 nanoseconds. - Weight::from_ref_time(9_618_711 as u64) - // Standard Error: 3_167 - .saturating_add(Weight::from_ref_time(133_543 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_434 nanoseconds. + Weight::from_ref_time(10_522_329) + // Standard Error: 3_124 + .saturating_add(Weight::from_ref_time(143_872).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) /// The range of component `r` is `[1, 19]`. fn set_account_id(r: u32, ) -> Weight { - // Minimum execution time: 8_921 nanoseconds. - Weight::from_ref_time(9_716_868 as u64) - // Standard Error: 2_614 - .saturating_add(Weight::from_ref_time(134_578 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_963 nanoseconds. + Weight::from_ref_time(10_676_629) + // Standard Error: 2_604 + .saturating_add(Weight::from_ref_time(150_719).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) /// The range of component `r` is `[1, 19]`. fn set_fields(r: u32, ) -> Weight { - // Minimum execution time: 8_737 nanoseconds. - Weight::from_ref_time(9_596_263 as u64) - // Standard Error: 2_774 - .saturating_add(Weight::from_ref_time(133_115 as u64).saturating_mul(r as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_743 nanoseconds. + Weight::from_ref_time(10_550_737) + // Standard Error: 2_567 + .saturating_add(Weight::from_ref_time(147_953).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) // Storage: Identity IdentityOf (r:1 w:1) /// The range of component `r` is `[1, 19]`. /// The range of component `x` is `[0, 100]`. fn provide_judgement(r: u32, x: u32, ) -> Weight { - // Minimum execution time: 27_898 nanoseconds. - Weight::from_ref_time(28_261_231 as u64) - // Standard Error: 4_462 - .saturating_add(Weight::from_ref_time(63_546 as u64).saturating_mul(r as u64)) - // Standard Error: 825 - .saturating_add(Weight::from_ref_time(519_389 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 30_156 nanoseconds. + Weight::from_ref_time(29_200_426) + // Standard Error: 7_041 + .saturating_add(Weight::from_ref_time(108_906).saturating_mul(r.into())) + // Standard Error: 1_302 + .saturating_add(Weight::from_ref_time(709_623).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Identity SubsOf (r:1 w:1) // Storage: Identity IdentityOf (r:1 w:1) @@ -192,62 +192,62 @@ impl pallet_identity::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. /// The range of component `x` is `[0, 100]`. fn kill_identity(r: u32, s: u32, x: u32, ) -> Weight { - // Minimum execution time: 54_613 nanoseconds. - Weight::from_ref_time(39_369_694 as u64) - // Standard Error: 4_703 - .saturating_add(Weight::from_ref_time(126_210 as u64).saturating_mul(r as u64)) - // Standard Error: 918 - .saturating_add(Weight::from_ref_time(895_761 as u64).saturating_mul(s as u64)) - // Standard Error: 918 - .saturating_add(Weight::from_ref_time(160_435 as u64).saturating_mul(x as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 59_119 nanoseconds. + Weight::from_ref_time(44_039_884) + // Standard Error: 7_474 + .saturating_add(Weight::from_ref_time(50_982).saturating_mul(r.into())) + // Standard Error: 1_459 + .saturating_add(Weight::from_ref_time(946_900).saturating_mul(s.into())) + // Standard Error: 1_459 + .saturating_add(Weight::from_ref_time(180_851).saturating_mul(x.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) // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[0, 99]`. fn add_sub(s: u32, ) -> Weight { - // Minimum execution time: 30_688 nanoseconds. - Weight::from_ref_time(37_399_108 as u64) - // Standard Error: 1_781 - .saturating_add(Weight::from_ref_time(70_488 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 33_731 nanoseconds. + Weight::from_ref_time(40_625_172) + // Standard Error: 2_022 + .saturating_add(Weight::from_ref_time(80_037).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) // Storage: Identity SuperOf (r:1 w:1) /// The range of component `s` is `[1, 100]`. fn rename_sub(s: u32, ) -> Weight { - // Minimum execution time: 13_869 nanoseconds. - Weight::from_ref_time(16_257_327 as u64) - // Standard Error: 736 - .saturating_add(Weight::from_ref_time(25_702 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 14_742 nanoseconds. + Weight::from_ref_time(17_467_279) + // Standard Error: 820 + .saturating_add(Weight::from_ref_time(26_321).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) // Storage: Identity SuperOf (r:1 w:1) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[1, 100]`. fn remove_sub(s: u32, ) -> Weight { - // Minimum execution time: 34_965 nanoseconds. - Weight::from_ref_time(39_002_236 as u64) - // Standard Error: 1_713 - .saturating_add(Weight::from_ref_time(60_309 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 37_703 nanoseconds. + Weight::from_ref_time(41_704_866) + // Standard Error: 1_199 + .saturating_add(Weight::from_ref_time(69_966).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) // Storage: Identity SubsOf (r:1 w:1) /// The range of component `s` is `[0, 99]`. fn quit_sub(s: u32, ) -> Weight { - // Minimum execution time: 25_199 nanoseconds. - Weight::from_ref_time(28_698_501 as u64) - // Standard Error: 1_176 - .saturating_add(Weight::from_ref_time(62_015 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 27_376 nanoseconds. + Weight::from_ref_time(30_933_613) + // Standard Error: 1_271 + .saturating_add(Weight::from_ref_time(67_357).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/westend/src/weights/pallet_im_online.rs b/runtime/westend/src/weights/pallet_im_online.rs index f2dff12e38c2..d46f8b875e6e 100644 --- a/runtime/westend/src/weights/pallet_im_online.rs +++ b/runtime/westend/src/weights/pallet_im_online.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_im_online` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -52,13 +52,13 @@ impl pallet_im_online::WeightInfo for WeightInfo { /// The range of component `k` is `[1, 1000]`. /// The range of component `e` is `[1, 100]`. fn validate_unsigned_and_then_heartbeat(k: u32, e: u32, ) -> Weight { - // Minimum execution time: 96_317 nanoseconds. - Weight::from_ref_time(77_388_779 as u64) - // Standard Error: 260 - .saturating_add(Weight::from_ref_time(22_806 as u64).saturating_mul(k as u64)) - // Standard Error: 2_628 - .saturating_add(Weight::from_ref_time(312_410 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 98_091 nanoseconds. + Weight::from_ref_time(77_799_094) + // Standard Error: 361 + .saturating_add(Weight::from_ref_time(26_154).saturating_mul(k.into())) + // Standard Error: 3_639 + .saturating_add(Weight::from_ref_time(336_844).saturating_mul(e.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/pallet_indices.rs b/runtime/westend/src/weights/pallet_indices.rs index 0e850d96405f..dab3f7a0f414 100644 --- a/runtime/westend/src/weights/pallet_indices.rs +++ b/runtime/westend/src/weights/pallet_indices.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_indices` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -46,39 +46,39 @@ pub struct WeightInfo(PhantomData); impl pallet_indices::WeightInfo for WeightInfo { // Storage: Indices Accounts (r:1 w:1) fn claim() -> Weight { - // Minimum execution time: 25_466 nanoseconds. - Weight::from_ref_time(25_778_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 27_689 nanoseconds. + Weight::from_ref_time(27_938_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn transfer() -> Weight { - // Minimum execution time: 31_634 nanoseconds. - Weight::from_ref_time(32_118_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 34_150 nanoseconds. + Weight::from_ref_time(34_750_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Indices Accounts (r:1 w:1) fn free() -> Weight { - // Minimum execution time: 26_841 nanoseconds. - Weight::from_ref_time(27_309_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 28_404 nanoseconds. + Weight::from_ref_time(28_873_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Indices Accounts (r:1 w:1) // Storage: System Account (r:1 w:1) fn force_transfer() -> Weight { - // Minimum execution time: 26_354 nanoseconds. - Weight::from_ref_time(26_911_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 28_767 nanoseconds. + Weight::from_ref_time(29_455_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Indices Accounts (r:1 w:1) fn freeze() -> Weight { - // Minimum execution time: 31_895 nanoseconds. - Weight::from_ref_time(32_621_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 33_923 nanoseconds. + Weight::from_ref_time(34_377_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/pallet_multisig.rs b/runtime/westend/src/weights/pallet_multisig.rs index e15f0973adae..6c1b22e4002f 100644 --- a/runtime/westend/src/weights/pallet_multisig.rs +++ b/runtime/westend/src/weights/pallet_multisig.rs @@ -16,8 +16,8 @@ //! Autogenerated weights for `pallet_multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-26, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bm2`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 // Executed Command: @@ -28,11 +28,11 @@ // --steps=50 // --repeat=20 // --pallet=pallet_multisig -// --extrinsic= +// --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --header=./file_header.txt -// --output=runtime/westend/src/weights/ +// --output=./runtime/westend/src/weights/ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -46,81 +46,81 @@ pub struct WeightInfo(PhantomData); impl pallet_multisig::WeightInfo for WeightInfo { /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { - // Minimum execution time: 14_417 nanoseconds. - Weight::from_ref_time(14_932_092 as u64) - // Standard Error: 2 - .saturating_add(Weight::from_ref_time(482 as u64).saturating_mul(z as u64)) + // Minimum execution time: 15_729 nanoseconds. + Weight::from_ref_time(16_089_045) + // Standard Error: 3 + .saturating_add(Weight::from_ref_time(706).saturating_mul(z.into())) } // Storage: Multisig Multisigs (r:1 w:1) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) /// 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 { - // Minimum execution time: 41_482 nanoseconds. - Weight::from_ref_time(34_353_792 as u64) - // Standard Error: 791 - .saturating_add(Weight::from_ref_time(81_017 as u64).saturating_mul(s as u64)) - // Standard Error: 7 - .saturating_add(Weight::from_ref_time(1_468 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 44_361 nanoseconds. + Weight::from_ref_time(36_207_202) + // Standard Error: 1_031 + .saturating_add(Weight::from_ref_time(91_962).saturating_mul(s.into())) + // Standard Error: 10 + .saturating_add(Weight::from_ref_time(1_751).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Multisig Multisigs (r:1 w:1) /// 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 { - // Minimum execution time: 32_410 nanoseconds. - Weight::from_ref_time(25_806_543 as u64) - // Standard Error: 602 - .saturating_add(Weight::from_ref_time(74_253 as u64).saturating_mul(s as u64)) - // Standard Error: 5 - .saturating_add(Weight::from_ref_time(1_463 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 35_346 nanoseconds. + Weight::from_ref_time(28_197_613) + // Standard Error: 640 + .saturating_add(Weight::from_ref_time(84_279).saturating_mul(s.into())) + // Standard Error: 6 + .saturating_add(Weight::from_ref_time(1_675).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) // Storage: System Account (r:1 w:1) /// 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 { - // Minimum execution time: 46_059 nanoseconds. - Weight::from_ref_time(37_295_248 as u64) - // Standard Error: 604 - .saturating_add(Weight::from_ref_time(104_164 as u64).saturating_mul(s as u64)) - // Standard Error: 5 - .saturating_add(Weight::from_ref_time(1_489 as u64).saturating_mul(z as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 49_935 nanoseconds. + Weight::from_ref_time(40_256_343) + // Standard Error: 990 + .saturating_add(Weight::from_ref_time(111_995).saturating_mul(s.into())) + // Standard Error: 9 + .saturating_add(Weight::from_ref_time(1_718).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) // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { - // Minimum execution time: 29_952 nanoseconds. - Weight::from_ref_time(32_697_678 as u64) - // Standard Error: 857 - .saturating_add(Weight::from_ref_time(86_644 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 31_975 nanoseconds. + Weight::from_ref_time(34_916_069) + // Standard Error: 1_145 + .saturating_add(Weight::from_ref_time(96_587).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Multisig Multisigs (r:1 w:1) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { - // Minimum execution time: 22_298 nanoseconds. - Weight::from_ref_time(23_997_404 as u64) - // Standard Error: 855 - .saturating_add(Weight::from_ref_time(82_455 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 24_180 nanoseconds. + Weight::from_ref_time(25_785_712) + // Standard Error: 698 + .saturating_add(Weight::from_ref_time(91_940).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) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { - // Minimum execution time: 31_615 nanoseconds. - Weight::from_ref_time(33_932_527 as u64) - // Standard Error: 823 - .saturating_add(Weight::from_ref_time(87_873 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 34_417 nanoseconds. + Weight::from_ref_time(36_684_842) + // Standard Error: 914 + .saturating_add(Weight::from_ref_time(89_800).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/pallet_nomination_pools.rs b/runtime/westend/src/weights/pallet_nomination_pools.rs index f8db33c4cc95..c205531c6e2d 100644 --- a/runtime/westend/src/weights/pallet_nomination_pools.rs +++ b/runtime/westend/src/weights/pallet_nomination_pools.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_nomination_pools` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -47,65 +47,66 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools MinJoinBond (r:1 w:0) // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:2 w:1) // Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) // Storage: NominationPools MaxPoolMembers (r:1 w:0) // Storage: NominationPools CounterForPoolMembers (r:1 w:1) - // Storage: Staking Bonded (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn join() -> Weight { - // Minimum execution time: 137_881 nanoseconds. - Weight::from_ref_time(139_554_000 as u64) - .saturating_add(T::DbWeight::get().reads(17 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) + // Minimum execution time: 146_592 nanoseconds. + Weight::from_ref_time(147_983_000) + .saturating_add(T::DbWeight::get().reads(17)) + .saturating_add(T::DbWeight::get().writes(12)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:3 w:2) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra_transfer() -> Weight { - // Minimum execution time: 135_618 nanoseconds. - Weight::from_ref_time(136_732_000 as u64) - .saturating_add(T::DbWeight::get().reads(14 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) + // Minimum execution time: 144_377 nanoseconds. + Weight::from_ref_time(145_658_000) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(12)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:3 w:3) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:0) + // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:2 w:2) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra_reward() -> Weight { - // Minimum execution time: 138_488 nanoseconds. - Weight::from_ref_time(139_721_000 as u64) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) + // Minimum execution time: 148_710 nanoseconds. + Weight::from_ref_time(151_603_000) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(12)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) // Storage: System Account (r:1 w:1) fn claim_payout() -> Weight { - // Minimum execution time: 54_599 nanoseconds. - Weight::from_ref_time(55_472_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 57_128 nanoseconds. + Weight::from_ref_time(58_023_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: System Account (r:2 w:1) // Storage: Staking CurrentEra (r:1 w:0) @@ -113,52 +114,53 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: Staking MinNominatorBond (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: VoterList ListNodes (r:3 w:3) - // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListBags (r:2 w:2) // Storage: NominationPools SubPoolsStorage (r:1 w:1) // Storage: NominationPools CounterForSubPoolsStorage (r:1 w:1) fn unbond() -> Weight { - // Minimum execution time: 137_493 nanoseconds. - Weight::from_ref_time(139_057_000 as u64) - .saturating_add(T::DbWeight::get().reads(18 as u64)) - .saturating_add(T::DbWeight::get().writes(13 as u64)) + // Minimum execution time: 147_189 nanoseconds. + Weight::from_ref_time(148_361_000) + .saturating_add(T::DbWeight::get().reads(18)) + .saturating_add(T::DbWeight::get().writes(13)) } // Storage: NominationPools BondedPools (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Balances Locks (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn pool_withdraw_unbonded(s: u32, ) -> Weight { - // Minimum execution time: 50_487 nanoseconds. - Weight::from_ref_time(52_064_084 as u64) - // Standard Error: 994 - .saturating_add(Weight::from_ref_time(19_109 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 58_826 nanoseconds. + Weight::from_ref_time(60_311_353) + // Standard Error: 1_105 + .saturating_add(Weight::from_ref_time(18_024).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools SubPoolsStorage (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: System Account (r:1 w:1) // Storage: NominationPools CounterForPoolMembers (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 90_722 nanoseconds. - Weight::from_ref_time(92_596_144 as u64) - // Standard Error: 1_246 - .saturating_add(Weight::from_ref_time(26_945 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 101_092 nanoseconds. + Weight::from_ref_time(102_915_910) + // Standard Error: 1_355 + .saturating_add(Weight::from_ref_time(12_954).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: NominationPools PoolMembers (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: NominationPools BondedPools (r:1 w:1) // Storage: NominationPools SubPoolsStorage (r:1 w:1) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) // Storage: Staking SlashingSpans (r:1 w:0) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:0) @@ -175,26 +177,26 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: Staking Payee (r:0 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { - // Minimum execution time: 143_281 nanoseconds. - Weight::from_ref_time(146_070_579 as u64) - // Standard Error: 2_405 - .saturating_add(Weight::from_ref_time(6_142 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(20 as u64)) - .saturating_add(T::DbWeight::get().writes(17 as u64)) + // Minimum execution time: 150_986 nanoseconds. + Weight::from_ref_time(152_731_576) + // Standard Error: 3_598 + .saturating_add(Weight::from_ref_time(25_042).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(20)) + .saturating_add(T::DbWeight::get().writes(17)) } + // Storage: NominationPools LastPoolId (r:1 w:1) // Storage: Staking MinNominatorBond (r:1 w:0) // Storage: NominationPools MinCreateBond (r:1 w:0) // Storage: NominationPools MinJoinBond (r:1 w:0) // Storage: NominationPools MaxPools (r:1 w:0) // Storage: NominationPools CounterForBondedPools (r:1 w:1) // Storage: NominationPools PoolMembers (r:1 w:1) - // Storage: NominationPools LastPoolId (r:1 w:1) // Storage: NominationPools MaxPoolMembersPerPool (r:1 w:0) // Storage: NominationPools MaxPoolMembers (r:1 w:0) // Storage: NominationPools CounterForPoolMembers (r:1 w:1) // Storage: System Account (r:2 w:2) - // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) + // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) // Storage: Balances Locks (r:1 w:1) // Storage: NominationPools RewardPools (r:1 w:1) @@ -204,52 +206,53 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools BondedPools (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn create() -> Weight { - // Minimum execution time: 126_730 nanoseconds. - Weight::from_ref_time(128_187_000 as u64) - .saturating_add(T::DbWeight::get().reads(21 as u64)) - .saturating_add(T::DbWeight::get().writes(15 as u64)) + // Minimum execution time: 132_988 nanoseconds. + Weight::from_ref_time(135_480_000) + .saturating_add(T::DbWeight::get().reads(21)) + .saturating_add(T::DbWeight::get().writes(15)) } // Storage: NominationPools BondedPools (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinNominatorBond (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) // Storage: Staking MaxNominatorsCount (r:1 w:0) // Storage: Staking Validators (r:2 w:0) // Storage: Staking CurrentEra (r:1 w:0) - // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListNodes (r:1 w:1) // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 61_915 nanoseconds. - Weight::from_ref_time(62_490_766 as u64) - // Standard Error: 6_804 - .saturating_add(Weight::from_ref_time(1_018_805 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 65_850 nanoseconds. + Weight::from_ref_time(66_406_389) + // Standard Error: 7_339 + .saturating_add(Weight::from_ref_time(1_099_535).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: NominationPools BondedPools (r:1 w:1) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) fn set_state() -> Weight { - // Minimum execution time: 34_674 nanoseconds. - Weight::from_ref_time(35_021_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 40_888 nanoseconds. + Weight::from_ref_time(41_373_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: NominationPools BondedPools (r:1 w:0) // Storage: NominationPools Metadata (r:1 w:1) // Storage: NominationPools CounterForMetadata (r:1 w:1) /// The range of component `n` is `[1, 256]`. fn set_metadata(n: u32, ) -> Weight { - // Minimum execution time: 16_346 nanoseconds. - Weight::from_ref_time(17_028_773 as u64) - // Standard Error: 386 - .saturating_add(Weight::from_ref_time(2_707 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 16_147 nanoseconds. + Weight::from_ref_time(16_753_550) + // Standard Error: 124 + .saturating_add(Weight::from_ref_time(1_891).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: NominationPools MinJoinBond (r:0 w:1) // Storage: NominationPools MaxPoolMembers (r:0 w:1) @@ -257,18 +260,19 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: NominationPools MinCreateBond (r:0 w:1) // Storage: NominationPools MaxPools (r:0 w:1) fn set_configs() -> Weight { - // Minimum execution time: 7_856 nanoseconds. - Weight::from_ref_time(8_041_000 as u64) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 6_720 nanoseconds. + Weight::from_ref_time(7_070_000) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: NominationPools BondedPools (r:1 w:1) fn update_roles() -> Weight { - // Minimum execution time: 26_630 nanoseconds. - Weight::from_ref_time(27_163_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_867 nanoseconds. + Weight::from_ref_time(27_243_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: NominationPools BondedPools (r:1 w:0) + // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Validators (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -277,9 +281,9 @@ impl pallet_nomination_pools::WeightInfo for WeightInfo // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Minimum execution time: 61_492 nanoseconds. - Weight::from_ref_time(62_308_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 65_683 nanoseconds. + Weight::from_ref_time(66_860_000) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(5)) } } diff --git a/runtime/westend/src/weights/pallet_preimage.rs b/runtime/westend/src/weights/pallet_preimage.rs index ac0d76756fd1..cbb9b5364399 100644 --- a/runtime/westend/src/weights/pallet_preimage.rs +++ b/runtime/westend/src/weights/pallet_preimage.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_preimage` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -48,99 +48,99 @@ impl pallet_preimage::WeightInfo for WeightInfo { // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_preimage(s: u32, ) -> Weight { - // Minimum execution time: 28_355 nanoseconds. - Weight::from_ref_time(28_676_000 as u64) + // Minimum execution time: 31_504 nanoseconds. + Weight::from_ref_time(31_935_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_294 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_485).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_requested_preimage(s: u32, ) -> Weight { - // Minimum execution time: 19_919 nanoseconds. - Weight::from_ref_time(20_111_000 as u64) + // Minimum execution time: 22_593 nanoseconds. + Weight::from_ref_time(23_018_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_289 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_483).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) /// The range of component `s` is `[0, 4194304]`. fn note_no_deposit_preimage(s: u32, ) -> Weight { - // Minimum execution time: 18_568 nanoseconds. - Weight::from_ref_time(18_881_000 as u64) + // Minimum execution time: 20_815 nanoseconds. + Weight::from_ref_time(21_064_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_290 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(2_482).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_preimage() -> Weight { - // Minimum execution time: 39_289 nanoseconds. - Weight::from_ref_time(40_546_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 41_697 nanoseconds. + Weight::from_ref_time(43_334_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unnote_no_deposit_preimage() -> Weight { - // Minimum execution time: 26_795 nanoseconds. - Weight::from_ref_time(27_740_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 27_784 nanoseconds. + Weight::from_ref_time(29_673_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_preimage() -> Weight { - // Minimum execution time: 25_599 nanoseconds. - Weight::from_ref_time(26_814_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 28_498 nanoseconds. + Weight::from_ref_time(37_154_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_no_deposit_preimage() -> Weight { - // Minimum execution time: 13_239 nanoseconds. - Weight::from_ref_time(14_310_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 18_137 nanoseconds. + Weight::from_ref_time(23_421_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_unnoted_preimage() -> Weight { - // Minimum execution time: 17_639 nanoseconds. - Weight::from_ref_time(18_295_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 22_082 nanoseconds. + Weight::from_ref_time(24_619_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn request_requested_preimage() -> Weight { - // Minimum execution time: 8_905 nanoseconds. - Weight::from_ref_time(9_273_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_382 nanoseconds. + Weight::from_ref_time(10_809_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) // Storage: Preimage PreimageFor (r:0 w:1) fn unrequest_preimage() -> Weight { - // Minimum execution time: 26_257 nanoseconds. - Weight::from_ref_time(27_156_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 32_096 nanoseconds. + Weight::from_ref_time(37_249_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_unnoted_preimage() -> Weight { - // Minimum execution time: 8_613 nanoseconds. - Weight::from_ref_time(8_924_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 10_427 nanoseconds. + Weight::from_ref_time(11_181_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Preimage StatusFor (r:1 w:1) fn unrequest_multi_referenced_preimage() -> Weight { - // Minimum execution time: 8_631 nanoseconds. - Weight::from_ref_time(9_177_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_917 nanoseconds. + Weight::from_ref_time(10_538_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/pallet_proxy.rs b/runtime/westend/src/weights/pallet_proxy.rs index 81a93cc4eb85..b48ceec5f560 100644 --- a/runtime/westend/src/weights/pallet_proxy.rs +++ b/runtime/westend/src/weights/pallet_proxy.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_proxy` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -47,11 +47,11 @@ impl pallet_proxy::WeightInfo for WeightInfo { // Storage: Proxy Proxies (r:1 w:0) /// The range of component `p` is `[1, 31]`. fn proxy(p: u32, ) -> Weight { - // Minimum execution time: 19_557 nanoseconds. - Weight::from_ref_time(20_990_890 as u64) - // Standard Error: 4_214 - .saturating_add(Weight::from_ref_time(49_337 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) + // Minimum execution time: 21_399 nanoseconds. + Weight::from_ref_time(22_441_170) + // Standard Error: 1_457 + .saturating_add(Weight::from_ref_time(46_573).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) } // Storage: Proxy Proxies (r:1 w:0) // Storage: Proxy Announcements (r:1 w:1) @@ -59,42 +59,42 @@ impl pallet_proxy::WeightInfo for WeightInfo { /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn proxy_announced(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 36_963 nanoseconds. - Weight::from_ref_time(37_873_141 as u64) - // Standard Error: 2_376 - .saturating_add(Weight::from_ref_time(112_476 as u64).saturating_mul(a as u64)) - // Standard Error: 2_455 - .saturating_add(Weight::from_ref_time(25_228 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 39_895 nanoseconds. + Weight::from_ref_time(40_556_198) + // Standard Error: 2_058 + .saturating_add(Weight::from_ref_time(125_126).saturating_mul(a.into())) + // Standard Error: 2_126 + .saturating_add(Weight::from_ref_time(34_236).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) // Storage: System Account (r:1 w:1) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn remove_announcement(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 25_553 nanoseconds. - Weight::from_ref_time(26_789_457 as u64) - // Standard Error: 1_681 - .saturating_add(Weight::from_ref_time(111_064 as u64).saturating_mul(a as u64)) - // Standard Error: 1_737 - .saturating_add(Weight::from_ref_time(4_487 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 27_567 nanoseconds. + Weight::from_ref_time(28_835_169) + // Standard Error: 1_771 + .saturating_add(Weight::from_ref_time(128_829).saturating_mul(a.into())) + // Standard Error: 1_830 + .saturating_add(Weight::from_ref_time(5_270).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) // Storage: System Account (r:1 w:1) /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn reject_announcement(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 25_532 nanoseconds. - Weight::from_ref_time(26_555_150 as u64) - // Standard Error: 1_544 - .saturating_add(Weight::from_ref_time(114_475 as u64).saturating_mul(a as u64)) - // Standard Error: 1_595 - .saturating_add(Weight::from_ref_time(7_001 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 27_682 nanoseconds. + Weight::from_ref_time(28_886_650) + // Standard Error: 1_745 + .saturating_add(Weight::from_ref_time(130_446).saturating_mul(a.into())) + // Standard Error: 1_803 + .saturating_add(Weight::from_ref_time(4_083).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) // Storage: Proxy Announcements (r:1 w:1) @@ -102,64 +102,64 @@ impl pallet_proxy::WeightInfo for WeightInfo { /// The range of component `a` is `[0, 31]`. /// The range of component `p` is `[1, 31]`. fn announce(a: u32, p: u32, ) -> Weight { - // Minimum execution time: 32_958 nanoseconds. - Weight::from_ref_time(34_690_880 as u64) - // Standard Error: 2_046 - .saturating_add(Weight::from_ref_time(98_030 as u64).saturating_mul(a as u64)) - // Standard Error: 2_114 - .saturating_add(Weight::from_ref_time(23_754 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 36_109 nanoseconds. + Weight::from_ref_time(37_592_683) + // Standard Error: 2_089 + .saturating_add(Weight::from_ref_time(115_406).saturating_mul(a.into())) + // Standard Error: 2_158 + .saturating_add(Weight::from_ref_time(24_877).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) /// The range of component `p` is `[1, 31]`. fn add_proxy(p: u32, ) -> Weight { - // Minimum execution time: 26_983 nanoseconds. - Weight::from_ref_time(28_481_463 as u64) - // Standard Error: 2_047 - .saturating_add(Weight::from_ref_time(63_259 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_354 nanoseconds. + Weight::from_ref_time(30_580_225) + // Standard Error: 1_939 + .saturating_add(Weight::from_ref_time(72_670).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) /// The range of component `p` is `[1, 31]`. fn remove_proxy(p: u32, ) -> Weight { - // Minimum execution time: 27_026 nanoseconds. - Weight::from_ref_time(28_423_344 as u64) - // Standard Error: 2_139 - .saturating_add(Weight::from_ref_time(80_532 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 29_405 nanoseconds. + Weight::from_ref_time(30_855_077) + // Standard Error: 2_387 + .saturating_add(Weight::from_ref_time(82_949).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) /// The range of component `p` is `[1, 31]`. fn remove_proxies(p: u32, ) -> Weight { - // Minimum execution time: 23_688 nanoseconds. - Weight::from_ref_time(25_488_979 as u64) - // Standard Error: 2_380 - .saturating_add(Weight::from_ref_time(7_566 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 25_164 nanoseconds. + Weight::from_ref_time(26_549_207) + // Standard Error: 1_846 + .saturating_add(Weight::from_ref_time(56_112).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: unknown [0x3a65787472696e7369635f696e646578] (r:1 w:0) // Storage: Proxy Proxies (r:1 w:1) /// The range of component `p` is `[1, 31]`. fn create_pure(p: u32, ) -> Weight { - // Minimum execution time: 28_914 nanoseconds. - Weight::from_ref_time(30_185_796 as u64) - // Standard Error: 1_784 - .saturating_add(Weight::from_ref_time(21_017 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 31_612 nanoseconds. + Weight::from_ref_time(32_862_431) + // Standard Error: 1_549 + .saturating_add(Weight::from_ref_time(32_604).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Proxy Proxies (r:1 w:1) /// The range of component `p` is `[0, 30]`. fn kill_pure(p: u32, ) -> Weight { - // Minimum execution time: 24_534 nanoseconds. - Weight::from_ref_time(25_747_053 as u64) - // Standard Error: 1_940 - .saturating_add(Weight::from_ref_time(51_750 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_741 nanoseconds. + Weight::from_ref_time(28_127_722) + // Standard Error: 1_387 + .saturating_add(Weight::from_ref_time(52_518).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/pallet_scheduler.rs b/runtime/westend/src/weights/pallet_scheduler.rs index 8e1e6ac2ad40..09d5dff7d238 100644 --- a/runtime/westend/src/weights/pallet_scheduler.rs +++ b/runtime/westend/src/weights/pallet_scheduler.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_scheduler` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -46,95 +46,95 @@ pub struct WeightInfo(PhantomData); impl pallet_scheduler::WeightInfo for WeightInfo { // Storage: Scheduler IncompleteSince (r:1 w:1) fn service_agendas_base() -> Weight { - // Minimum execution time: 4_370 nanoseconds. - Weight::from_ref_time(4_502_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_853 nanoseconds. + Weight::from_ref_time(4_987_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 50]`. fn service_agenda_base(s: u32, ) -> Weight { - // Minimum execution time: 3_700 nanoseconds. - Weight::from_ref_time(6_822_653 as u64) - // Standard Error: 1_792 - .saturating_add(Weight::from_ref_time(567_987 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_088 nanoseconds. + Weight::from_ref_time(7_576_495) + // Standard Error: 2_156 + .saturating_add(Weight::from_ref_time(682_589).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } fn service_task_base() -> Weight { - // Minimum execution time: 9_223 nanoseconds. - Weight::from_ref_time(9_738_000 as u64) + // Minimum execution time: 9_943 nanoseconds. + Weight::from_ref_time(10_099_000) } // Storage: Preimage PreimageFor (r:1 w:1) // Storage: Preimage StatusFor (r:1 w:1) /// The range of component `s` is `[128, 4194304]`. fn service_task_fetched(s: u32, ) -> Weight { - // Minimum execution time: 21_101 nanoseconds. - Weight::from_ref_time(21_454_000 as u64) + // Minimum execution time: 23_143 nanoseconds. + Weight::from_ref_time(23_294_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(1_250 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(1_452).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:0 w:1) fn service_task_named() -> Weight { - // Minimum execution time: 10_837 nanoseconds. - Weight::from_ref_time(11_168_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 11_359 nanoseconds. + Weight::from_ref_time(11_578_000) + .saturating_add(T::DbWeight::get().writes(1)) } fn service_task_periodic() -> Weight { - // Minimum execution time: 9_286 nanoseconds. - Weight::from_ref_time(9_582_000 as u64) + // Minimum execution time: 10_300 nanoseconds. + Weight::from_ref_time(10_636_000) } fn execute_dispatch_signed() -> Weight { - // Minimum execution time: 4_038 nanoseconds. - Weight::from_ref_time(4_184_000 as u64) + // Minimum execution time: 4_505 nanoseconds. + Weight::from_ref_time(4_602_000) } fn execute_dispatch_unsigned() -> Weight { - // Minimum execution time: 3_949 nanoseconds. - Weight::from_ref_time(4_057_000 as u64) + // Minimum execution time: 4_555 nanoseconds. + Weight::from_ref_time(4_663_000) } // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 49]`. fn schedule(s: u32, ) -> Weight { - // Minimum execution time: 16_889 nanoseconds. - Weight::from_ref_time(21_346_740 as u64) - // Standard Error: 2_567 - .saturating_add(Weight::from_ref_time(588_527 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 18_425 nanoseconds. + Weight::from_ref_time(22_633_918) + // Standard Error: 2_496 + .saturating_add(Weight::from_ref_time(703_880).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) // Storage: Scheduler Lookup (r:0 w:1) /// The range of component `s` is `[1, 50]`. fn cancel(s: u32, ) -> Weight { - // Minimum execution time: 20_050 nanoseconds. - Weight::from_ref_time(21_672_769 as u64) - // Standard Error: 1_963 - .saturating_add(Weight::from_ref_time(584_093 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 21_138 nanoseconds. + Weight::from_ref_time(23_083_032) + // Standard Error: 2_037 + .saturating_add(Weight::from_ref_time(694_640).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[0, 49]`. fn schedule_named(s: u32, ) -> Weight { - // Minimum execution time: 20_220 nanoseconds. - Weight::from_ref_time(24_461_622 as u64) - // Standard Error: 3_061 - .saturating_add(Weight::from_ref_time(616_499 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 21_140 nanoseconds. + Weight::from_ref_time(26_422_364) + // Standard Error: 3_390 + .saturating_add(Weight::from_ref_time(725_818).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Scheduler Lookup (r:1 w:1) // Storage: Scheduler Agenda (r:1 w:1) /// The range of component `s` is `[1, 50]`. fn cancel_named(s: u32, ) -> Weight { - // Minimum execution time: 20_855 nanoseconds. - Weight::from_ref_time(23_510_708 as u64) - // Standard Error: 2_186 - .saturating_add(Weight::from_ref_time(591_211 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 22_159 nanoseconds. + Weight::from_ref_time(24_970_672) + // Standard Error: 2_367 + .saturating_add(Weight::from_ref_time(706_983).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } } diff --git a/runtime/westend/src/weights/pallet_session.rs b/runtime/westend/src/weights/pallet_session.rs index b0f5ab30a788..20d751fc3279 100644 --- a/runtime/westend/src/weights/pallet_session.rs +++ b/runtime/westend/src/weights/pallet_session.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_session` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -48,18 +48,18 @@ impl pallet_session::WeightInfo for WeightInfo { // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:6 w:6) fn set_keys() -> Weight { - // Minimum execution time: 49_017 nanoseconds. - Weight::from_ref_time(50_530_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 52_642 nanoseconds. + Weight::from_ref_time(54_045_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Session NextKeys (r:1 w:1) // Storage: Session KeyOwner (r:0 w:6) fn purge_keys() -> Weight { - // Minimum execution time: 37_075 nanoseconds. - Weight::from_ref_time(38_290_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 39_810 nanoseconds. + Weight::from_ref_time(41_128_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(7)) } } diff --git a/runtime/westend/src/weights/pallet_staking.rs b/runtime/westend/src/weights/pallet_staking.rs index 125e45df12ef..eea1a93d112a 100644 --- a/runtime/westend/src/weights/pallet_staking.rs +++ b/runtime/westend/src/weights/pallet_staking.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_staking` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -50,10 +50,10 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) fn bond() -> Weight { - // Minimum execution time: 44_919 nanoseconds. - Weight::from_ref_time(46_102_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 48_229 nanoseconds. + Weight::from_ref_time(48_858_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Staking Bonded (r:1 w:0) // Storage: Staking Ledger (r:1 w:1) @@ -61,10 +61,10 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListNodes (r:3 w:3) // Storage: VoterList ListBags (r:2 w:2) fn bond_extra() -> Weight { - // Minimum execution time: 80_191 nanoseconds. - Weight::from_ref_time(80_953_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 85_680 nanoseconds. + Weight::from_ref_time(87_091_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Staking Ledger (r:1 w:1) // Storage: Staking Nominators (r:1 w:0) @@ -76,10 +76,10 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking Bonded (r:1 w:0) // Storage: VoterList ListBags (r:2 w:2) fn unbond() -> Weight { - // Minimum execution time: 86_967 nanoseconds. - Weight::from_ref_time(87_679_000 as u64) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 94_521 nanoseconds. + Weight::from_ref_time(95_544_000) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) @@ -87,12 +87,12 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { - // Minimum execution time: 37_885 nanoseconds. - Weight::from_ref_time(40_160_684 as u64) - // Standard Error: 962 - .saturating_add(Weight::from_ref_time(23_334 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 41_030 nanoseconds. + Weight::from_ref_time(42_947_403) + // Standard Error: 2_438 + .saturating_add(Weight::from_ref_time(30_194).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Staking Ledger (r:1 w:1) // Storage: Staking CurrentEra (r:1 w:0) @@ -107,14 +107,16 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) // Storage: Balances Locks (r:1 w:1) // Storage: Staking Payee (r:0 w:1) + // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { - // Minimum execution time: 73_247 nanoseconds. - Weight::from_ref_time(75_284_540 as u64) - // Standard Error: 1_277 - .saturating_add(Weight::from_ref_time(2_814 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(11 as u64)) + // Minimum execution time: 83_163 nanoseconds. + Weight::from_ref_time(86_233_015) + // Standard Error: 2_393 + .saturating_add(Weight::from_ref_time(928_106).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(12)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinValidatorBond (r:1 w:0) @@ -128,22 +130,22 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList CounterForListNodes (r:1 w:1) // Storage: Staking CounterForValidators (r:1 w:1) fn validate() -> Weight { - // Minimum execution time: 59_417 nanoseconds. - Weight::from_ref_time(60_321_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 62_008 nanoseconds. + Weight::from_ref_time(63_087_000) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { - // Minimum execution time: 32_309 nanoseconds. - Weight::from_ref_time(30_379_999 as u64) - // Standard Error: 9_757 - .saturating_add(Weight::from_ref_time(6_283_375 as u64).saturating_mul(k as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(k as u64))) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(k as u64))) + // Minimum execution time: 34_929 nanoseconds. + Weight::from_ref_time(31_879_035) + // Standard Error: 10_923 + .saturating_add(Weight::from_ref_time(6_688_720).saturating_mul(k.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking MinNominatorBond (r:1 w:0) @@ -158,13 +160,13 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking CounterForNominators (r:1 w:1) /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { - // Minimum execution time: 61_031 nanoseconds. - Weight::from_ref_time(60_371_065 as u64) - // Standard Error: 5_826 - .saturating_add(Weight::from_ref_time(2_367_944 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 66_268 nanoseconds. + Weight::from_ref_time(65_653_232) + // Standard Error: 5_918 + .saturating_add(Weight::from_ref_time(2_488_204).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Validators (r:1 w:0) @@ -174,59 +176,59 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill() -> Weight { - // Minimum execution time: 55_977 nanoseconds. - Weight::from_ref_time(57_202_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 61_090 nanoseconds. + Weight::from_ref_time(61_782_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Payee (r:0 w:1) fn set_payee() -> Weight { - // Minimum execution time: 15_597 nanoseconds. - Weight::from_ref_time(15_845_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 17_559 nanoseconds. + Weight::from_ref_time(17_868_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking Ledger (r:2 w:2) fn set_controller() -> Weight { - // Minimum execution time: 22_414 nanoseconds. - Weight::from_ref_time(22_860_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 24_679 nanoseconds. + Weight::from_ref_time(25_329_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Staking ValidatorCount (r:0 w:1) fn set_validator_count() -> Weight { - // Minimum execution time: 4_099 nanoseconds. - Weight::from_ref_time(4_249_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_017 nanoseconds. + Weight::from_ref_time(5_112_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_no_eras() -> Weight { - // Minimum execution time: 4_276 nanoseconds. - Weight::from_ref_time(4_378_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_055 nanoseconds. + Weight::from_ref_time(5_308_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era() -> Weight { - // Minimum execution time: 4_106 nanoseconds. - Weight::from_ref_time(4_214_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_131 nanoseconds. + Weight::from_ref_time(5_263_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking ForceEra (r:0 w:1) fn force_new_era_always() -> Weight { - // Minimum execution time: 4_221 nanoseconds. - Weight::from_ref_time(4_402_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 5_157 nanoseconds. + Weight::from_ref_time(5_389_000) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Invulnerables (r:0 w:1) /// The range of component `v` is `[0, 1000]`. fn set_invulnerables(v: u32, ) -> Weight { - // Minimum execution time: 4_150 nanoseconds. - Weight::from_ref_time(4_728_614 as u64) + // Minimum execution time: 5_189 nanoseconds. + Weight::from_ref_time(5_738_244) // Standard Error: 32 - .saturating_add(Weight::from_ref_time(11_345 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(13_575).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking Bonded (r:1 w:1) // Storage: Staking SlashingSpans (r:1 w:0) @@ -243,23 +245,23 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking SpanSlash (r:0 w:2) /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { - // Minimum execution time: 67_687 nanoseconds. - Weight::from_ref_time(72_720_204 as u64) - // Standard Error: 1_921 - .saturating_add(Weight::from_ref_time(878_716 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 74_401 nanoseconds. + Weight::from_ref_time(78_982_441) + // Standard Error: 2_215 + .saturating_add(Weight::from_ref_time(935_788).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(12)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: Staking UnappliedSlashes (r:1 w:1) /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { - // Minimum execution time: 118_556 nanoseconds. - Weight::from_ref_time(1_335_997_093 as u64) - // Standard Error: 88_697 - .saturating_add(Weight::from_ref_time(7_439_050 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 117_983 nanoseconds. + Weight::from_ref_time(942_878_048) + // Standard Error: 59_395 + .saturating_add(Weight::from_ref_time(4_934_238).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking ErasValidatorReward (r:1 w:0) @@ -272,14 +274,14 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: System Account (r:1 w:1) /// The range of component `n` is `[0, 64]`. fn payout_stakers_dead_controller(n: u32, ) -> Weight { - // Minimum execution time: 75_734 nanoseconds. - Weight::from_ref_time(89_504_336 as u64) - // Standard Error: 24_913 - .saturating_add(Weight::from_ref_time(19_162_630 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(n as u64))) + // Minimum execution time: 79_618 nanoseconds. + Weight::from_ref_time(97_391_462) + // Standard Error: 27_066 + .saturating_add(Weight::from_ref_time(20_709_371).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) } // Storage: Staking CurrentEra (r:1 w:0) // Storage: Staking ErasValidatorReward (r:1 w:0) @@ -293,14 +295,14 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Balances Locks (r:1 w:1) /// The range of component `n` is `[0, 64]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { - // Minimum execution time: 87_803 nanoseconds. - Weight::from_ref_time(111_266_197 as u64) - // Standard Error: 36_584 - .saturating_add(Weight::from_ref_time(25_512_336 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(n as u64))) + // Minimum execution time: 93_560 nanoseconds. + Weight::from_ref_time(122_070_975) + // Standard Error: 39_617 + .saturating_add(Weight::from_ref_time(27_759_630).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(3)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) } // Storage: Staking Ledger (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -310,12 +312,12 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListBags (r:2 w:2) /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { - // Minimum execution time: 79_272 nanoseconds. - Weight::from_ref_time(81_092_805 as u64) - // Standard Error: 4_327 - .saturating_add(Weight::from_ref_time(40_862 as u64).saturating_mul(l as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 85_541 nanoseconds. + Weight::from_ref_time(87_582_465) + // Standard Error: 4_756 + .saturating_add(Weight::from_ref_time(22_919).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: System Account (r:1 w:1) // Storage: Staking Bonded (r:1 w:1) @@ -332,16 +334,15 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking SpanSlash (r:0 w:1) /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { - // Minimum execution time: 79_673 nanoseconds. - Weight::from_ref_time(80_100_348 as u64) - // Standard Error: 2_843 - .saturating_add(Weight::from_ref_time(886_290 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(12 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(s as u64))) + // Minimum execution time: 84_676 nanoseconds. + Weight::from_ref_time(86_956_205) + // Standard Error: 2_062 + .saturating_add(Weight::from_ref_time(932_163).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(12)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) } // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: Staking SlashingSpans (r:1 w:0) // Storage: VoterList ListBags (r:178 w:0) // Storage: VoterList ListNodes (r:101 w:0) // Storage: Staking Nominators (r:101 w:0) @@ -358,23 +359,23 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking ErasStakers (r:0 w:1) // Storage: Staking ErasTotalStake (r:0 w:1) // Storage: Staking ErasStartSessionIndex (r:0 w:1) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[1, 10]`. /// The range of component `n` is `[0, 100]`. fn new_era(v: u32, n: u32, ) -> Weight { - // Minimum execution time: 444_099 nanoseconds. - Weight::from_ref_time(462_116_000 as u64) - // Standard Error: 1_825_380 - .saturating_add(Weight::from_ref_time(60_582_117 as u64).saturating_mul(v as u64)) - // Standard Error: 181_889 - .saturating_add(Weight::from_ref_time(12_617_609 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(186 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(v as u64))) + // Minimum execution time: 447_775 nanoseconds. + Weight::from_ref_time(449_912_000) + // Standard Error: 1_875_211 + .saturating_add(Weight::from_ref_time(61_748_001).saturating_mul(v.into())) + // Standard Error: 186_854 + .saturating_add(Weight::from_ref_time(13_671_156).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(185)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(5)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(v.into()))) } // Storage: VoterList CounterForListNodes (r:1 w:0) - // Storage: Staking SlashingSpans (r:21 w:0) // Storage: VoterList ListBags (r:178 w:0) // Storage: VoterList ListNodes (r:1500 w:0) // Storage: Staking Nominators (r:1500 w:0) @@ -382,34 +383,33 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking Bonded (r:1500 w:0) // Storage: Staking Ledger (r:1500 w:0) // Storage: System BlockWeight (r:1 w:1) + // Storage: Staking MinimumActiveStake (r:0 w:1) /// The range of component `v` is `[500, 1000]`. /// The range of component `n` is `[500, 1000]`. - /// The range of component `s` is `[1, 20]`. - fn get_npos_voters(v: u32, n: u32, s: u32, ) -> Weight { - // Minimum execution time: 25_695_485 nanoseconds. - Weight::from_ref_time(25_860_451_000 as u64) - // Standard Error: 472_700 - .saturating_add(Weight::from_ref_time(11_577_066 as u64).saturating_mul(v as u64)) - // Standard Error: 472_700 - .saturating_add(Weight::from_ref_time(10_734_019 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(181 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(s as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + fn get_npos_voters(v: u32, n: u32, ) -> Weight { + // Minimum execution time: 25_749_836 nanoseconds. + Weight::from_ref_time(25_911_941_000) + // Standard Error: 598_364 + .saturating_add(Weight::from_ref_time(5_189_738).saturating_mul(v.into())) + // Standard Error: 598_364 + .saturating_add(Weight::from_ref_time(5_161_223).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(180)) + .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Staking CounterForValidators (r:1 w:0) // Storage: Staking Validators (r:501 w:0) // Storage: System BlockWeight (r:1 w:1) /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { - // Minimum execution time: 3_409_575 nanoseconds. - Weight::from_ref_time(110_440_394 as u64) - // Standard Error: 43_738 - .saturating_add(Weight::from_ref_time(6_940_019 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(v as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 3_683_939 nanoseconds. + Weight::from_ref_time(3_768_534_000) + // Standard Error: 43_790 + .saturating_add(Weight::from_ref_time(2_923_468).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Staking MinCommission (r:0 w:1) // Storage: Staking MinValidatorBond (r:0 w:1) @@ -418,9 +418,9 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_set() -> Weight { - // Minimum execution time: 7_596 nanoseconds. - Weight::from_ref_time(7_822_000 as u64) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 9_167 nanoseconds. + Weight::from_ref_time(14_979_000) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:0 w:1) // Storage: Staking MinValidatorBond (r:0 w:1) @@ -429,9 +429,9 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: Staking MaxNominatorsCount (r:0 w:1) // Storage: Staking MinNominatorBond (r:0 w:1) fn set_staking_configs_all_remove() -> Weight { - // Minimum execution time: 6_748 nanoseconds. - Weight::from_ref_time(7_052_000 as u64) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 7_552 nanoseconds. + Weight::from_ref_time(7_922_000) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking Ledger (r:1 w:0) // Storage: Staking Nominators (r:1 w:1) @@ -444,17 +444,17 @@ impl pallet_staking::WeightInfo for WeightInfo { // Storage: VoterList ListBags (r:1 w:1) // Storage: VoterList CounterForListNodes (r:1 w:1) fn chill_other() -> Weight { - // Minimum execution time: 66_366 nanoseconds. - Weight::from_ref_time(66_789_000 as u64) - .saturating_add(T::DbWeight::get().reads(11 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Minimum execution time: 71_662 nanoseconds. + Weight::from_ref_time(72_346_000) + .saturating_add(T::DbWeight::get().reads(11)) + .saturating_add(T::DbWeight::get().writes(6)) } // Storage: Staking MinCommission (r:1 w:0) // Storage: Staking Validators (r:1 w:1) fn force_apply_min_commission() -> Weight { - // Minimum execution time: 15_138 nanoseconds. - Weight::from_ref_time(15_465_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 15_807 nanoseconds. + Weight::from_ref_time(16_049_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/pallet_timestamp.rs b/runtime/westend/src/weights/pallet_timestamp.rs index 9e2c99779daa..2e506a4fea81 100644 --- a/runtime/westend/src/weights/pallet_timestamp.rs +++ b/runtime/westend/src/weights/pallet_timestamp.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_timestamp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -47,13 +47,13 @@ impl pallet_timestamp::WeightInfo for WeightInfo { // Storage: Timestamp Now (r:1 w:1) // Storage: Babe CurrentSlot (r:1 w:0) fn set() -> Weight { - // Minimum execution time: 9_068 nanoseconds. - Weight::from_ref_time(9_294_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 9_955 nanoseconds. + Weight::from_ref_time(10_423_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } fn on_finalize() -> Weight { - // Minimum execution time: 3_838 nanoseconds. - Weight::from_ref_time(4_004_000 as u64) + // Minimum execution time: 4_237 nanoseconds. + Weight::from_ref_time(4_391_000) } } diff --git a/runtime/westend/src/weights/pallet_utility.rs b/runtime/westend/src/weights/pallet_utility.rs index f976ff6b788e..646f1498cd8e 100644 --- a/runtime/westend/src/weights/pallet_utility.rs +++ b/runtime/westend/src/weights/pallet_utility.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_utility` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -46,31 +46,31 @@ pub struct WeightInfo(PhantomData); impl pallet_utility::WeightInfo for WeightInfo { /// The range of component `c` is `[0, 1000]`. fn batch(c: u32, ) -> Weight { - // Minimum execution time: 11_344 nanoseconds. - Weight::from_ref_time(15_084_816 as u64) - // Standard Error: 2_719 - .saturating_add(Weight::from_ref_time(3_318_885 as u64).saturating_mul(c as u64)) + // Minimum execution time: 12_703 nanoseconds. + Weight::from_ref_time(15_425_383) + // Standard Error: 2_789 + .saturating_add(Weight::from_ref_time(3_670_420).saturating_mul(c.into())) } fn as_derivative() -> Weight { - // Minimum execution time: 5_807 nanoseconds. - Weight::from_ref_time(6_033_000 as u64) + // Minimum execution time: 6_362 nanoseconds. + Weight::from_ref_time(6_480_000) } /// The range of component `c` is `[0, 1000]`. fn batch_all(c: u32, ) -> Weight { - // Minimum execution time: 11_444 nanoseconds. - Weight::from_ref_time(18_634_415 as u64) - // Standard Error: 3_166 - .saturating_add(Weight::from_ref_time(3_479_338 as u64).saturating_mul(c as u64)) + // Minimum execution time: 13_246 nanoseconds. + Weight::from_ref_time(18_237_502) + // Standard Error: 2_863 + .saturating_add(Weight::from_ref_time(3_867_822).saturating_mul(c.into())) } fn dispatch_as() -> Weight { - // Minimum execution time: 13_410 nanoseconds. - Weight::from_ref_time(13_821_000 as u64) + // Minimum execution time: 14_913 nanoseconds. + Weight::from_ref_time(15_296_000) } /// The range of component `c` is `[0, 1000]`. fn force_batch(c: u32, ) -> Weight { - // Minimum execution time: 11_023 nanoseconds. - Weight::from_ref_time(14_615_133 as u64) - // Standard Error: 2_404 - .saturating_add(Weight::from_ref_time(3_327_844 as u64).saturating_mul(c as u64)) + // Minimum execution time: 12_629 nanoseconds. + Weight::from_ref_time(16_700_925) + // Standard Error: 2_728 + .saturating_add(Weight::from_ref_time(3_679_666).saturating_mul(c.into())) } } diff --git a/runtime/westend/src/weights/pallet_vesting.rs b/runtime/westend/src/weights/pallet_vesting.rs index 642836238f61..7c96f96106b6 100644 --- a/runtime/westend/src/weights/pallet_vesting.rs +++ b/runtime/westend/src/weights/pallet_vesting.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `pallet_vesting` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -49,28 +49,28 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_locked(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 37_183 nanoseconds. - Weight::from_ref_time(36_684_277 as u64) - // Standard Error: 1_065 - .saturating_add(Weight::from_ref_time(40_600 as u64).saturating_mul(l as u64)) - // Standard Error: 1_895 - .saturating_add(Weight::from_ref_time(69_083 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 40_380 nanoseconds. + Weight::from_ref_time(39_367_952) + // Standard Error: 1_385 + .saturating_add(Weight::from_ref_time(51_428).saturating_mul(l.into())) + // Standard Error: 2_465 + .saturating_add(Weight::from_ref_time(79_669).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[1, 28]`. fn vest_unlocked(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 37_040 nanoseconds. - Weight::from_ref_time(36_422_009 as u64) - // Standard Error: 1_110 - .saturating_add(Weight::from_ref_time(39_319 as u64).saturating_mul(l as u64)) - // Standard Error: 1_975 - .saturating_add(Weight::from_ref_time(57_199 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 39_567 nanoseconds. + Weight::from_ref_time(38_893_789) + // Standard Error: 1_215 + .saturating_add(Weight::from_ref_time(48_517).saturating_mul(l.into())) + // Standard Error: 2_162 + .saturating_add(Weight::from_ref_time(70_277).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -78,14 +78,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 37_003 nanoseconds. - Weight::from_ref_time(36_545_448 as u64) - // Standard Error: 1_175 - .saturating_add(Weight::from_ref_time(38_723 as u64).saturating_mul(l as u64)) - // Standard Error: 2_091 - .saturating_add(Weight::from_ref_time(68_390 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 40_234 nanoseconds. + Weight::from_ref_time(38_730_793) + // Standard Error: 1_240 + .saturating_add(Weight::from_ref_time(55_041).saturating_mul(l.into())) + // Standard Error: 2_207 + .saturating_add(Weight::from_ref_time(95_472).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -93,14 +93,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 36_641 nanoseconds. - Weight::from_ref_time(36_355_534 as u64) - // Standard Error: 1_145 - .saturating_add(Weight::from_ref_time(40_167 as u64).saturating_mul(l as u64)) - // Standard Error: 2_037 - .saturating_add(Weight::from_ref_time(45_324 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 39_705 nanoseconds. + Weight::from_ref_time(39_246_321) + // Standard Error: 1_381 + .saturating_add(Weight::from_ref_time(45_703).saturating_mul(l.into())) + // Standard Error: 2_457 + .saturating_add(Weight::from_ref_time(55_853).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:1 w:1) @@ -108,14 +108,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// The range of component `l` is `[0, 49]`. /// The range of component `s` is `[0, 27]`. fn vested_transfer(l: u32, s: u32, ) -> Weight { - // Minimum execution time: 50_555 nanoseconds. - Weight::from_ref_time(51_170_903 as u64) - // Standard Error: 1_907 - .saturating_add(Weight::from_ref_time(45_993 as u64).saturating_mul(l as u64)) - // Standard Error: 3_393 - .saturating_add(Weight::from_ref_time(22_249 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 54_821 nanoseconds. + Weight::from_ref_time(55_267_572) + // Standard Error: 1_793 + .saturating_add(Weight::from_ref_time(42_698).saturating_mul(l.into())) + // Standard Error: 3_191 + .saturating_add(Weight::from_ref_time(43_262).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: System Account (r:2 w:2) @@ -123,14 +123,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 50_181 nanoseconds. - Weight::from_ref_time(50_424_666 as u64) - // Standard Error: 1_780 - .saturating_add(Weight::from_ref_time(37_337 as u64).saturating_mul(l as u64)) - // Standard Error: 3_167 - .saturating_add(Weight::from_ref_time(43_062 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 54_411 nanoseconds. + Weight::from_ref_time(55_014_023) + // Standard Error: 2_225 + .saturating_add(Weight::from_ref_time(39_475).saturating_mul(l.into())) + // Standard Error: 3_959 + .saturating_add(Weight::from_ref_time(37_900).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -138,14 +138,14 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 38_284 nanoseconds. - Weight::from_ref_time(37_590_291 as u64) - // Standard Error: 1_161 - .saturating_add(Weight::from_ref_time(42_501 as u64).saturating_mul(l as u64)) - // Standard Error: 2_144 - .saturating_add(Weight::from_ref_time(70_327 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 41_139 nanoseconds. + Weight::from_ref_time(40_433_577) + // Standard Error: 1_263 + .saturating_add(Weight::from_ref_time(48_108).saturating_mul(l.into())) + // Standard Error: 2_333 + .saturating_add(Weight::from_ref_time(79_141).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Vesting Vesting (r:1 w:1) // Storage: Balances Locks (r:1 w:1) @@ -153,13 +153,13 @@ impl pallet_vesting::WeightInfo for WeightInfo { /// 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 { - // Minimum execution time: 38_261 nanoseconds. - Weight::from_ref_time(38_137_437 as u64) - // Standard Error: 1_243 - .saturating_add(Weight::from_ref_time(37_066 as u64).saturating_mul(l as u64)) - // Standard Error: 2_296 - .saturating_add(Weight::from_ref_time(48_166 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 41_563 nanoseconds. + Weight::from_ref_time(40_428_260) + // Standard Error: 1_304 + .saturating_add(Weight::from_ref_time(49_855).saturating_mul(l.into())) + // Standard Error: 2_408 + .saturating_add(Weight::from_ref_time(82_149).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/westend/src/weights/runtime_common_auctions.rs b/runtime/westend/src/weights/runtime_common_auctions.rs index 285c4e03fa47..e0bb8b4569fc 100644 --- a/runtime/westend/src/weights/runtime_common_auctions.rs +++ b/runtime/westend/src/weights/runtime_common_auctions.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::auctions` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -47,10 +47,10 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Auctions AuctionInfo (r:1 w:1) // Storage: Auctions AuctionCounter (r:1 w:1) fn new_auction() -> Weight { - // Minimum execution time: 16_493 nanoseconds. - Weight::from_ref_time(17_345_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 17_789 nanoseconds. + Weight::from_ref_time(18_219_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Paras ParaLifecycles (r:1 w:0) // Storage: Auctions AuctionCounter (r:1 w:0) @@ -60,10 +60,10 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Auctions ReservedAmounts (r:2 w:2) // Storage: System Account (r:1 w:1) fn bid() -> Weight { - // Minimum execution time: 70_142 nanoseconds. - Weight::from_ref_time(71_728_000 as u64) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 74_919 nanoseconds. + Weight::from_ref_time(76_318_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Auctions AuctionInfo (r:1 w:1) // Storage: Babe NextRandomness (r:1 w:0) @@ -78,19 +78,19 @@ impl runtime_common::auctions::WeightInfo for WeightInf // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar Paras (r:1 w:1) fn on_initialize() -> Weight { - // Minimum execution time: 14_569_286 nanoseconds. - Weight::from_ref_time(14_838_470_000 as u64) - .saturating_add(T::DbWeight::get().reads(3688 as u64)) - .saturating_add(T::DbWeight::get().writes(3683 as u64)) + // Minimum execution time: 15_538_306 nanoseconds. + Weight::from_ref_time(15_841_046_000) + .saturating_add(T::DbWeight::get().reads(3688)) + .saturating_add(T::DbWeight::get().writes(3683)) } // Storage: Auctions ReservedAmounts (r:37 w:36) // Storage: System Account (r:36 w:36) // Storage: Auctions Winning (r:0 w:3600) // Storage: Auctions AuctionInfo (r:0 w:1) fn cancel_auction() -> Weight { - // Minimum execution time: 4_522_777 nanoseconds. - Weight::from_ref_time(4_617_937_000 as u64) - .saturating_add(T::DbWeight::get().reads(73 as u64)) - .saturating_add(T::DbWeight::get().writes(3673 as u64)) + // Minimum execution time: 4_599_501 nanoseconds. + Weight::from_ref_time(4_720_502_000) + .saturating_add(T::DbWeight::get().reads(73)) + .saturating_add(T::DbWeight::get().writes(3673)) } } diff --git a/runtime/westend/src/weights/runtime_common_crowdloan.rs b/runtime/westend/src/weights/runtime_common_crowdloan.rs index 96b147a6bbb3..91a2694aa020 100644 --- a/runtime/westend/src/weights/runtime_common_crowdloan.rs +++ b/runtime/westend/src/weights/runtime_common_crowdloan.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::crowdloan` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -49,75 +49,77 @@ impl runtime_common::crowdloan::WeightInfo for WeightIn // Storage: Paras ParaLifecycles (r:1 w:0) // Storage: Crowdloan NextFundIndex (r:1 w:1) fn create() -> Weight { - // Minimum execution time: 47_331 nanoseconds. - Weight::from_ref_time(48_516_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 49_682 nanoseconds. + Weight::from_ref_time(50_541_000) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: Slots Leases (r:1 w:0) // Storage: Auctions AuctionInfo (r:1 w:0) // Storage: System Account (r:1 w:1) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: Crowdloan EndingsCount (r:1 w:0) // Storage: Crowdloan NewRaise (r:1 w:1) // Storage: unknown [0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291] (r:1 w:1) fn contribute() -> Weight { - // Minimum execution time: 113_791 nanoseconds. - Weight::from_ref_time(115_542_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 120_926 nanoseconds. + Weight::from_ref_time(122_594_000) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: System Account (r:2 w:2) + // Storage: Balances InactiveIssuance (r:1 w:1) // Storage: unknown [0xc85982571aa615c788ef9b2c16f54f25773fd439e8ee1ed2aa3ae43d48e880f0] (r:1 w:1) fn withdraw() -> Weight { - // Minimum execution time: 53_602 nanoseconds. - Weight::from_ref_time(54_469_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 60_197 nanoseconds. + Weight::from_ref_time(61_179_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Skipped Metadata (r:0 w:0) /// The range of component `k` is `[0, 500]`. fn refund(k: u32, ) -> Weight { - // Minimum execution time: 50_291 nanoseconds. - Weight::from_ref_time(25_006_147 as u64) - // Standard Error: 12_114 - .saturating_add(Weight::from_ref_time(17_108_181 as u64).saturating_mul(k as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(k as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(k as u64))) + // Minimum execution time: 53_020 nanoseconds. + Weight::from_ref_time(18_744_226) + // Standard Error: 13_787 + .saturating_add(Weight::from_ref_time(18_958_635).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(3)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(k.into()))) } // Storage: Crowdloan Funds (r:1 w:1) // Storage: System Account (r:1 w:1) fn dissolve() -> Weight { - // Minimum execution time: 35_498 nanoseconds. - Weight::from_ref_time(36_398_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 36_923 nanoseconds. + Weight::from_ref_time(38_140_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Crowdloan Funds (r:1 w:1) fn edit() -> Weight { - // Minimum execution time: 24_490 nanoseconds. - Weight::from_ref_time(25_285_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 25_850 nanoseconds. + Weight::from_ref_time(26_610_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Crowdloan Funds (r:1 w:0) // Storage: unknown [0xd861ea1ebf4800d4b89f4ff787ad79ee96d9a708c85b57da7eb8f9ddeda61291] (r:1 w:1) fn add_memo() -> Weight { - // Minimum execution time: 31_245 nanoseconds. - Weight::from_ref_time(32_197_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 33_319 nanoseconds. + Weight::from_ref_time(33_959_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Crowdloan Funds (r:1 w:0) // Storage: Crowdloan NewRaise (r:1 w:1) fn poke() -> Weight { - // Minimum execution time: 24_309 nanoseconds. - Weight::from_ref_time(25_069_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 26_264 nanoseconds. + Weight::from_ref_time(27_181_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Auctions AuctionInfo (r:1 w:0) // Storage: Crowdloan EndingsCount (r:1 w:1) @@ -131,13 +133,13 @@ impl runtime_common::crowdloan::WeightInfo for WeightIn // Storage: System Account (r:2 w:2) /// The range of component `n` is `[2, 100]`. fn on_initialize(n: u32, ) -> Weight { - // Minimum execution time: 99_726 nanoseconds. - Weight::from_ref_time(17_907_029 as u64) - // Standard Error: 36_455 - .saturating_add(Weight::from_ref_time(39_077_749 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().reads((5 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(n as u64))) + // Minimum execution time: 106_204 nanoseconds. + Weight::from_ref_time(13_571_340) + // Standard Error: 39_246 + .saturating_add(Weight::from_ref_time(42_499_164).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)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(n.into()))) } } diff --git a/runtime/westend/src/weights/runtime_common_paras_registrar.rs b/runtime/westend/src/weights/runtime_common_paras_registrar.rs index db1aca349373..7d0b7fee59a7 100644 --- a/runtime/westend/src/weights/runtime_common_paras_registrar.rs +++ b/runtime/westend/src/weights/runtime_common_paras_registrar.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::paras_registrar` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -48,10 +48,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:0) fn reserve() -> Weight { - // Minimum execution time: 32_661 nanoseconds. - Weight::from_ref_time(33_021_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 33_634 nanoseconds. + Weight::from_ref_time(34_233_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -63,10 +63,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras CurrentCodeHash (r:0 w:1) // Storage: Paras UpcomingParasGenesis (r:0 w:1) fn register() -> Weight { - // Minimum execution time: 7_278_260 nanoseconds. - Weight::from_ref_time(7_402_107_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 7_889_233 nanoseconds. + Weight::from_ref_time(7_969_248_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -78,10 +78,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras CurrentCodeHash (r:0 w:1) // Storage: Paras UpcomingParasGenesis (r:0 w:1) fn force_register() -> Weight { - // Minimum execution time: 7_254_460 nanoseconds. - Weight::from_ref_time(7_389_063_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) + // Minimum execution time: 7_817_133 nanoseconds. + Weight::from_ref_time(7_954_858_000) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(7)) } // Storage: Registrar Paras (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -90,10 +90,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar PendingSwap (r:0 w:1) fn deregister() -> Weight { - // Minimum execution time: 48_086 nanoseconds. - Weight::from_ref_time(49_772_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 51_071 nanoseconds. + Weight::from_ref_time(51_758_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Registrar Paras (r:1 w:0) // Storage: Paras ParaLifecycles (r:2 w:2) @@ -103,10 +103,10 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Crowdloan Funds (r:2 w:2) // Storage: Slots Leases (r:2 w:2) fn swap() -> Weight { - // Minimum execution time: 42_929 nanoseconds. - Weight::from_ref_time(43_993_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 45_428 nanoseconds. + Weight::from_ref_time(46_493_000) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras FutureCodeHash (r:1 w:1) // Storage: Paras UpgradeRestrictionSignal (r:1 w:1) @@ -120,20 +120,20 @@ impl runtime_common::paras_registrar::WeightInfo for We // Storage: Paras FutureCodeUpgrades (r:0 w:1) /// The range of component `b` is `[1, 3145728]`. fn schedule_code_upgrade(b: u32, ) -> Weight { - // Minimum execution time: 41_885 nanoseconds. - Weight::from_ref_time(42_261_000 as u64) + // Minimum execution time: 45_002 nanoseconds. + Weight::from_ref_time(45_518_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_287 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + .saturating_add(Weight::from_ref_time(2_487).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras Heads (r:0 w:1) /// The range of component `b` is `[1, 1048576]`. fn set_current_head(b: u32, ) -> Weight { - // Minimum execution time: 13_794 nanoseconds. - Weight::from_ref_time(13_978_000 as u64) + // Minimum execution time: 14_792 nanoseconds. + Weight::from_ref_time(14_975_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(909 as u64).saturating_mul(b as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(1_070).saturating_mul(b.into())) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/runtime_common_slots.rs b/runtime/westend/src/weights/runtime_common_slots.rs index a35984f6301f..54f465342c86 100644 --- a/runtime/westend/src/weights/runtime_common_slots.rs +++ b/runtime/westend/src/weights/runtime_common_slots.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_common::slots` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -47,40 +47,40 @@ impl runtime_common::slots::WeightInfo for WeightInfo Weight { - // Minimum execution time: 30_044 nanoseconds. - Weight::from_ref_time(30_999_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Minimum execution time: 34_409 nanoseconds. + Weight::from_ref_time(34_895_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: Paras Parachains (r:1 w:0) // Storage: Slots Leases (r:101 w:100) - // Storage: Paras ParaLifecycles (r:101 w:101) + // Storage: Paras ParaLifecycles (r:100 w:100) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) // Storage: Paras ActionsQueue (r:1 w:1) // Storage: Registrar Paras (r:100 w:100) - /// The range of component `c` is `[1, 100]`. - /// The range of component `t` is `[1, 100]`. + /// 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 { - // Minimum execution time: 541_004 nanoseconds. - Weight::from_ref_time(544_395_000 as u64) - // Standard Error: 67_401 - .saturating_add(Weight::from_ref_time(2_009_663 as u64).saturating_mul(c as u64)) - // Standard Error: 67_401 - .saturating_add(Weight::from_ref_time(11_680_248 as u64).saturating_mul(t as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(t as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(t as u64))) + // Minimum execution time: 552_213 nanoseconds. + Weight::from_ref_time(558_639_000) + // Standard Error: 69_329 + .saturating_add(Weight::from_ref_time(2_323_517).saturating_mul(c.into())) + // Standard Error: 69_329 + .saturating_add(Weight::from_ref_time(12_591_535).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().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()))) } // Storage: Slots Leases (r:1 w:1) // Storage: System Account (r:8 w:8) fn clear_all_leases() -> Weight { - // Minimum execution time: 90_911 nanoseconds. - Weight::from_ref_time(92_388_000 as u64) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) + // Minimum execution time: 102_709 nanoseconds. + Weight::from_ref_time(117_734_000) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(9)) } // Storage: Slots Leases (r:1 w:0) // Storage: Paras ParaLifecycles (r:1 w:1) @@ -88,9 +88,9 @@ impl runtime_common::slots::WeightInfo for WeightInfo Weight { - // Minimum execution time: 28_595 nanoseconds. - Weight::from_ref_time(29_454_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 33_393 nanoseconds. + Weight::from_ref_time(35_738_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } } diff --git a/runtime/westend/src/weights/runtime_parachains_configuration.rs b/runtime/westend/src/weights/runtime_parachains_configuration.rs index 6e5d038fb28f..70bdbfbc9cff 100644 --- a/runtime/westend/src/weights/runtime_parachains_configuration.rs +++ b/runtime/westend/src/weights/runtime_parachains_configuration.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::configuration` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -48,50 +48,50 @@ impl runtime_parachains::configuration::WeightInfo for // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_block_number() -> Weight { - // Minimum execution time: 11_758 nanoseconds. - Weight::from_ref_time(12_108_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 13_223 nanoseconds. + Weight::from_ref_time(13_661_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_u32() -> Weight { - // Minimum execution time: 11_677 nanoseconds. - Weight::from_ref_time(12_033_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 13_033 nanoseconds. + Weight::from_ref_time(13_422_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_option_u32() -> Weight { - // Minimum execution time: 11_585 nanoseconds. - Weight::from_ref_time(11_987_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 13_233 nanoseconds. + Weight::from_ref_time(13_459_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_weight() -> Weight { - // Minimum execution time: 11_946 nanoseconds. - Weight::from_ref_time(12_664_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 13_238 nanoseconds. + Weight::from_ref_time(13_908_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Benchmark Override (r:0 w:0) fn set_hrmp_open_request_ttl() -> Weight { // Minimum execution time: 2_000_000_000 nanoseconds. - Weight::from_ref_time(2_000_000_000_000 as u64) + Weight::from_ref_time(2_000_000_000_000) } // Storage: Configuration PendingConfigs (r:1 w:1) // Storage: Configuration BypassConsistencyCheck (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) fn set_config_with_balance() -> Weight { - // Minimum execution time: 11_939 nanoseconds. - Weight::from_ref_time(12_308_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 12_976 nanoseconds. + Weight::from_ref_time(13_433_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/runtime_parachains_disputes.rs b/runtime/westend/src/weights/runtime_parachains_disputes.rs index 51d07e29738d..13b5af7baea9 100644 --- a/runtime/westend/src/weights/runtime_parachains_disputes.rs +++ b/runtime/westend/src/weights/runtime_parachains_disputes.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::disputes` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -46,8 +46,8 @@ pub struct WeightInfo(PhantomData); impl runtime_parachains::disputes::WeightInfo for WeightInfo { // Storage: ParasDisputes Frozen (r:0 w:1) fn force_unfreeze() -> Weight { - // Minimum execution time: 4_324 nanoseconds. - Weight::from_ref_time(4_436_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 4_522 nanoseconds. + Weight::from_ref_time(4_719_000) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/runtime_parachains_disputes_slashing.rs b/runtime/westend/src/weights/runtime_parachains_disputes_slashing.rs index d9f0c357924a..5946f0f9ae1e 100644 --- a/runtime/westend/src/weights/runtime_parachains_disputes_slashing.rs +++ b/runtime/westend/src/weights/runtime_parachains_disputes_slashing.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::disputes::slashing` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -58,11 +58,11 @@ impl runtime_parachains::disputes::slashing::WeightInfo // Storage: Staking ValidatorSlashInEra (r:1 w:0) /// The range of component `n` is `[4, 300]`. fn report_dispute_lost(n: u32, ) -> Weight { - // Minimum execution time: 84_907 nanoseconds. - Weight::from_ref_time(98_263_914 as u64) - // Standard Error: 2_933 - .saturating_add(Weight::from_ref_time(224_882 as u64).saturating_mul(n as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 92_781 nanoseconds. + Weight::from_ref_time(106_750_804) + // Standard Error: 3_003 + .saturating_add(Weight::from_ref_time(234_660).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(4)) } } diff --git a/runtime/westend/src/weights/runtime_parachains_hrmp.rs b/runtime/westend/src/weights/runtime_parachains_hrmp.rs index 22748116ec4c..f8e9518d9f52 100644 --- a/runtime/westend/src/weights/runtime_parachains_hrmp.rs +++ b/runtime/westend/src/weights/runtime_parachains_hrmp.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::hrmp` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -53,10 +53,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_init_open_channel() -> Weight { - // Minimum execution time: 39_666 nanoseconds. - Weight::from_ref_time(40_166_000 as u64) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) + // Minimum execution time: 43_917 nanoseconds. + Weight::from_ref_time(44_362_000) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(5)) } // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) // Storage: Paras ParaLifecycles (r:1 w:0) @@ -65,10 +65,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_accept_open_channel() -> Weight { - // Minimum execution time: 39_648 nanoseconds. - Weight::from_ref_time(39_947_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 42_369 nanoseconds. + Weight::from_ref_time(43_251_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Hrmp HrmpChannels (r:1 w:0) // Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) @@ -76,10 +76,10 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) // Storage: Dmp DownwardMessageQueues (r:1 w:1) fn hrmp_close_channel() -> Weight { - // Minimum execution time: 36_824 nanoseconds. - Weight::from_ref_time(37_134_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 38_591 nanoseconds. + Weight::from_ref_time(39_570_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127) // Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1) @@ -90,18 +90,18 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf /// 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 { - // Minimum execution time: 847_678 nanoseconds. - Weight::from_ref_time(852_106_000 as u64) - // Standard Error: 76_785 - .saturating_add(Weight::from_ref_time(2_651_145 as u64).saturating_mul(i as u64)) - // Standard Error: 76_785 - .saturating_add(Weight::from_ref_time(2_718_986 as u64).saturating_mul(e as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(e as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(e as u64))) + // Minimum execution time: 897_819 nanoseconds. + Weight::from_ref_time(902_600_000) + // Standard Error: 82_324 + .saturating_add(Weight::from_ref_time(2_829_565).saturating_mul(i.into())) + // Standard Error: 82_324 + .saturating_add(Weight::from_ref_time(2_838_434).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()))) + .saturating_add(T::DbWeight::get().writes(4)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(i.into()))) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(e.into()))) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0) // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) @@ -113,14 +113,14 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpChannels (r:0 w:2) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_open(c: u32, ) -> Weight { - // Minimum execution time: 9_264 nanoseconds. - Weight::from_ref_time(9_446_000 as u64) - // Standard Error: 10_471 - .saturating_add(Weight::from_ref_time(15_482_563 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((7 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((6 as u64).saturating_mul(c as u64))) + // Minimum execution time: 10_578 nanoseconds. + Weight::from_ref_time(1_653_589) + // Standard Error: 18_210 + .saturating_add(Weight::from_ref_time(16_416_142).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()))) } // Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0) // Storage: Hrmp HrmpChannels (r:2 w:2) @@ -130,39 +130,39 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpChannelContents (r:0 w:2) /// The range of component `c` is `[0, 128]`. fn force_process_hrmp_close(c: u32, ) -> Weight { - // Minimum execution time: 6_075 nanoseconds. - Weight::from_ref_time(6_228_000 as u64) - // Standard Error: 7_996 - .saturating_add(Weight::from_ref_time(9_374_518 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((5 as u64).saturating_mul(c as u64))) + // Minimum execution time: 7_168 nanoseconds. + Weight::from_ref_time(7_254_000) + // Standard Error: 7_374 + .saturating_add(Weight::from_ref_time(9_950_496).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()))) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) /// The range of component `c` is `[0, 128]`. fn hrmp_cancel_open_request(c: u32, ) -> Weight { - // Minimum execution time: 24_597 nanoseconds. - Weight::from_ref_time(30_816_203 as u64) - // Standard Error: 1_397 - .saturating_add(Weight::from_ref_time(91_413 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 26_546 nanoseconds. + Weight::from_ref_time(32_577_364) + // Standard Error: 1_362 + .saturating_add(Weight::from_ref_time(98_626).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) /// The range of component `c` is `[0, 128]`. fn clean_open_channel_requests(c: u32, ) -> Weight { - // Minimum execution time: 4_151 nanoseconds. - Weight::from_ref_time(2_597_333 as u64) - // Standard Error: 3_958 - .saturating_add(Weight::from_ref_time(2_517_259 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + // Minimum execution time: 4_742 nanoseconds. + Weight::from_ref_time(3_317_809) + // Standard Error: 3_693 + .saturating_add(Weight::from_ref_time(2_619_705).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()))) } // Storage: Paras ParaLifecycles (r:2 w:0) // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) @@ -175,9 +175,9 @@ impl runtime_parachains::hrmp::WeightInfo for WeightInf // Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) fn force_open_hrmp_channel() -> Weight { - // Minimum execution time: 51_284 nanoseconds. - Weight::from_ref_time(51_911_000 as u64) - .saturating_add(T::DbWeight::get().reads(13 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + // Minimum execution time: 54_456 nanoseconds. + Weight::from_ref_time(55_129_000) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(8)) } } diff --git a/runtime/westend/src/weights/runtime_parachains_initializer.rs b/runtime/westend/src/weights/runtime_parachains_initializer.rs index 547ee04cc5b4..c63df05cd27e 100644 --- a/runtime/westend/src/weights/runtime_parachains_initializer.rs +++ b/runtime/westend/src/weights/runtime_parachains_initializer.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::initializer` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -47,11 +47,11 @@ impl runtime_parachains::initializer::WeightInfo for We // Storage: System Digest (r:1 w:1) /// The range of component `d` is `[0, 65536]`. fn force_approve(d: u32, ) -> Weight { - // Minimum execution time: 7_456 nanoseconds. - Weight::from_ref_time(10_280_250 as u64) + // Minimum execution time: 8_245 nanoseconds. + Weight::from_ref_time(11_065_500) // Standard Error: 7 - .saturating_add(Weight::from_ref_time(1_325 as u64).saturating_mul(d as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(1_321).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/runtime/westend/src/weights/runtime_parachains_paras.rs b/runtime/westend/src/weights/runtime_parachains_paras.rs index 9e8dbe1d2911..9994a9df747c 100644 --- a/runtime/westend/src/weights/runtime_parachains_paras.rs +++ b/runtime/westend/src/weights/runtime_parachains_paras.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::paras` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -52,21 +52,21 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras CodeByHash (r:0 w:1) /// The range of component `c` is `[1, 3145728]`. fn force_set_current_code(c: u32, ) -> Weight { - // Minimum execution time: 35_035 nanoseconds. - Weight::from_ref_time(35_691_000 as u64) + // Minimum execution time: 38_597 nanoseconds. + Weight::from_ref_time(39_125_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_273 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + .saturating_add(Weight::from_ref_time(2_472).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) /// The range of component `s` is `[1, 1048576]`. fn force_set_current_head(s: u32, ) -> Weight { - // Minimum execution time: 13_034 nanoseconds. - Weight::from_ref_time(13_260_000 as u64) + // Minimum execution time: 13_713 nanoseconds. + Weight::from_ref_time(13_856_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(908 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(1_069).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras FutureCodeHash (r:1 w:1) // Storage: Paras CurrentCodeHash (r:1 w:0) @@ -80,60 +80,60 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras UpgradeRestrictionSignal (r:0 w:1) /// The range of component `c` is `[1, 3145728]`. fn force_schedule_code_upgrade(c: u32, ) -> Weight { - // Minimum execution time: 60_031 nanoseconds. - Weight::from_ref_time(60_460_000 as u64) + // Minimum execution time: 65_408 nanoseconds. + Weight::from_ref_time(65_781_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_296 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(8 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) + .saturating_add(Weight::from_ref_time(2_492).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(8)) } // Storage: Paras FutureCodeUpgrades (r:1 w:0) // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) /// The range of component `s` is `[1, 1048576]`. fn force_note_new_head(s: u32, ) -> Weight { - // Minimum execution time: 18_669 nanoseconds. - Weight::from_ref_time(18_980_000 as u64) + // Minimum execution time: 19_951 nanoseconds. + Weight::from_ref_time(20_237_000) // Standard Error: 2 - .saturating_add(Weight::from_ref_time(913 as u64).saturating_mul(s as u64)) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + .saturating_add(Weight::from_ref_time(1_067).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) // Storage: Paras ActionsQueue (r:1 w:1) fn force_queue_action() -> Weight { - // Minimum execution time: 23_275 nanoseconds. - Weight::from_ref_time(23_770_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 25_010 nanoseconds. + Weight::from_ref_time(25_535_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras PvfActiveVoteMap (r:1 w:0) // Storage: Paras CodeByHash (r:1 w:1) /// The range of component `c` is `[1, 3145728]`. fn add_trusted_validation_code(c: u32, ) -> Weight { - // Minimum execution time: 8_351 nanoseconds. - Weight::from_ref_time(8_516_000 as u64) + // Minimum execution time: 9_464 nanoseconds. + Weight::from_ref_time(9_696_000) // Standard Error: 1 - .saturating_add(Weight::from_ref_time(2_277 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(Weight::from_ref_time(2_478).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: Paras CodeByHashRefs (r:1 w:0) // Storage: Paras CodeByHash (r:0 w:1) fn poke_unused_validation_code() -> Weight { - // Minimum execution time: 6_620 nanoseconds. - Weight::from_ref_time(6_767_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 7_497 nanoseconds. + Weight::from_ref_time(7_566_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) // Storage: Paras PvfActiveVoteMap (r:1 w:1) fn include_pvf_check_statement() -> Weight { - // Minimum execution time: 92_438 nanoseconds. - Weight::from_ref_time(94_776_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 93_014 nanoseconds. + Weight::from_ref_time(95_787_000) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) @@ -143,10 +143,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: System Digest (r:1 w:1) // Storage: Paras FutureCodeUpgrades (r:0 w:100) fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { - // Minimum execution time: 618_923 nanoseconds. - Weight::from_ref_time(622_876_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(104 as u64)) + // Minimum execution time: 665_749 nanoseconds. + Weight::from_ref_time(673_167_000) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(104)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) @@ -157,10 +157,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras UpgradeGoAheadSignal (r:0 w:100) // Storage: Paras FutureCodeHash (r:0 w:100) fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { - // Minimum execution time: 581_556 nanoseconds. - Weight::from_ref_time(592_174_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(204 as u64)) + // Minimum execution time: 629_664 nanoseconds. + Weight::from_ref_time(637_935_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(204)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) @@ -168,10 +168,10 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras PvfActiveVoteList (r:1 w:1) // Storage: Paras ActionsQueue (r:1 w:1) fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { - // Minimum execution time: 482_129 nanoseconds. - Weight::from_ref_time(489_028_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Minimum execution time: 517_474 nanoseconds. + Weight::from_ref_time(521_580_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) // Storage: ParasShared CurrentSessionIndex (r:1 w:0) @@ -183,9 +183,9 @@ impl runtime_parachains::paras::WeightInfo for WeightIn // Storage: Paras CurrentCodeHash (r:0 w:100) // Storage: Paras UpcomingParasGenesis (r:0 w:100) fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { - // Minimum execution time: 653_424 nanoseconds. - Weight::from_ref_time(658_874_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(304 as u64)) + // Minimum execution time: 699_356 nanoseconds. + Weight::from_ref_time(719_508_000) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(304)) } } diff --git a/runtime/westend/src/weights/runtime_parachains_paras_inherent.rs b/runtime/westend/src/weights/runtime_parachains_paras_inherent.rs index 2f61936f372a..520901a706af 100644 --- a/runtime/westend/src/weights/runtime_parachains_paras_inherent.rs +++ b/runtime/westend/src/weights/runtime_parachains_paras_inherent.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::paras_inherent` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -79,12 +79,12 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: ParasSlashing UnappliedSlashes (r:0 w:1) /// The range of component `v` is `[10, 200]`. fn enter_variable_disputes(v: u32, ) -> Weight { - // Minimum execution time: 806_508 nanoseconds. - Weight::from_ref_time(337_261_198 as u64) - // Standard Error: 22_890 - .saturating_add(Weight::from_ref_time(48_582_166 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(29 as u64)) - .saturating_add(T::DbWeight::get().writes(18 as u64)) + // Minimum execution time: 834_898 nanoseconds. + Weight::from_ref_time(372_495_289) + // Standard Error: 26_994 + .saturating_add(Weight::from_ref_time(48_296_040).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(29)) + .saturating_add(T::DbWeight::get().writes(18)) } // Storage: ParaInherent Included (r:1 w:1) // Storage: System ParentHash (r:1 w:0) @@ -117,10 +117,10 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) fn enter_bitfields() -> Weight { - // Minimum execution time: 323_004 nanoseconds. - Weight::from_ref_time(335_636_000 as u64) - .saturating_add(T::DbWeight::get().reads(26 as u64)) - .saturating_add(T::DbWeight::get().writes(17 as u64)) + // Minimum execution time: 346_792 nanoseconds. + Weight::from_ref_time(354_173_000) + .saturating_add(T::DbWeight::get().reads(26)) + .saturating_add(T::DbWeight::get().writes(17)) } // Storage: ParaInherent Included (r:1 w:1) // Storage: System ParentHash (r:1 w:0) @@ -155,12 +155,12 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) /// The range of component `v` is `[101, 200]`. fn enter_backed_candidates_variable(v: u32, ) -> Weight { - // Minimum execution time: 5_639_626 nanoseconds. - Weight::from_ref_time(858_049_168 as u64) - // Standard Error: 48_040 - .saturating_add(Weight::from_ref_time(48_211_579 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(29 as u64)) - .saturating_add(T::DbWeight::get().writes(16 as u64)) + // Minimum execution time: 5_715_617 nanoseconds. + Weight::from_ref_time(982_972_842) + // Standard Error: 48_959 + .saturating_add(Weight::from_ref_time(47_653_655).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) // Storage: System ParentHash (r:1 w:0) @@ -196,9 +196,9 @@ impl runtime_parachains::paras_inherent::WeightInfo for // Storage: Paras Heads (r:0 w:1) // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) fn enter_backed_candidate_code_upgrade() -> Weight { - // Minimum execution time: 38_038_548 nanoseconds. - Weight::from_ref_time(38_312_200_000 as u64) - .saturating_add(T::DbWeight::get().reads(31 as u64)) - .saturating_add(T::DbWeight::get().writes(16 as u64)) + // Minimum execution time: 41_119_951 nanoseconds. + Weight::from_ref_time(41_358_203_000) + .saturating_add(T::DbWeight::get().reads(31)) + .saturating_add(T::DbWeight::get().writes(16)) } } diff --git a/runtime/westend/src/weights/runtime_parachains_ump.rs b/runtime/westend/src/weights/runtime_parachains_ump.rs index 3643473c5592..ee03c139428f 100644 --- a/runtime/westend/src/weights/runtime_parachains_ump.rs +++ b/runtime/westend/src/weights/runtime_parachains_ump.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `runtime_parachains::ump` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-25, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-12-15, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! HOSTNAME: `bm5`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 @@ -46,26 +46,26 @@ pub struct WeightInfo(PhantomData); impl runtime_parachains::ump::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 51200]`. fn process_upward_message(s: u32, ) -> Weight { - // Minimum execution time: 10_148 nanoseconds. - Weight::from_ref_time(4_501_650 as u64) + // Minimum execution time: 11_067 nanoseconds. + Weight::from_ref_time(5_521_928) // Standard Error: 13 - .saturating_add(Weight::from_ref_time(1_889 as u64).saturating_mul(s as u64)) + .saturating_add(Weight::from_ref_time(2_043).saturating_mul(s.into())) } // Storage: Ump NeedsDispatch (r:1 w:1) // Storage: Ump NextDispatchRoundStartWith (r:1 w:1) // Storage: Ump RelayDispatchQueues (r:0 w:1) // Storage: Ump RelayDispatchQueueSize (r:0 w:1) fn clean_ump_after_outgoing() -> Weight { - // Minimum execution time: 9_117 nanoseconds. - Weight::from_ref_time(9_367_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) + // Minimum execution time: 10_126 nanoseconds. + Weight::from_ref_time(10_329_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(4)) } // Storage: Ump Overweight (r:1 w:1) fn service_overweight() -> Weight { - // Minimum execution time: 24_649 nanoseconds. - Weight::from_ref_time(25_163_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Minimum execution time: 27_891 nanoseconds. + Weight::from_ref_time(28_092_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } } diff --git a/scripts/ci/gitlab/lingua.dic b/scripts/ci/gitlab/lingua.dic index 3a19233a8fb9..a2f64af1cbd6 100644 --- a/scripts/ci/gitlab/lingua.dic +++ b/scripts/ci/gitlab/lingua.dic @@ -209,6 +209,7 @@ preconfigured preimage/MS preopen prepend/G +prevalidating prevalidation preverify/G programmatically diff --git a/scripts/ci/gitlab/pipeline/build.yml b/scripts/ci/gitlab/pipeline/build.yml index 791b01c2b632..c1ec964e96b2 100644 --- a/scripts/ci/gitlab/pipeline/build.yml +++ b/scripts/ci/gitlab/pipeline/build.yml @@ -22,7 +22,6 @@ build-linux-stable: RUN_UI_TESTS: 1 script: - time cargo build --profile testnet --features pyroscope --verbose --bin polkadot - - sccache -s # pack artifacts - mkdir -p ./artifacts - VERSION="${CI_COMMIT_REF_NAME}" # will be tag or branch name @@ -54,9 +53,11 @@ check-transaction-versions: - npm install --ignore-scripts -g @polkadot/metadata-cmp # Set git config - git config remote.origin.url "https://github.com/paritytech/polkadot.git" - - git fetch origin release + # - git fetch origin release script: - ./scripts/ci/gitlab/check_extrinsics_ordering.sh + # TODO: fixme, more info https://github.com/paritytech/polkadot/issues/6422 + allow_failure: true build-test-collators: stage: build @@ -73,7 +74,6 @@ build-test-collators: script: - time cargo build --profile testnet --verbose -p test-parachain-adder-collator - time cargo build --profile testnet --verbose -p test-parachain-undying-collator - - sccache -s # pack artifacts - mkdir -p ./artifacts - mv ./target/testnet/adder-collator ./artifacts/. @@ -98,7 +98,6 @@ build-malus: - .collect-artifacts script: - time cargo build --profile testnet --verbose -p polkadot-test-malus - - sccache -s # pack artifacts - mkdir -p ./artifacts - mv ./target/testnet/malus ./artifacts/. @@ -165,17 +164,18 @@ build-implementers-guide: - job: test-deterministic-wasm artifacts: false extends: - - .docker-env + - .kubernetes-env - .test-refs - .collect-artifacts-short + # git depth is set on purpose: https://github.com/paritytech/polkadot/issues/6284 + variables: + GIT_STRATEGY: clone + GIT_DEPTH: 0 + CI_IMAGE: paritytech/mdbook-utils:e14aae4a-20221123 script: - - apt-get -y update; apt-get install -y graphviz - - cargo install mdbook mdbook-mermaid mdbook-linkcheck mdbook-graphviz - mdbook build ./roadmap/implementers-guide - mkdir -p artifacts - mv roadmap/implementers-guide/book artifacts/ - # FIXME: remove me after CI image gets nonroot - - chown -R nonroot:nonroot artifacts/ build-short-benchmark: stage: build diff --git a/scripts/ci/gitlab/pipeline/check.yml b/scripts/ci/gitlab/pipeline/check.yml index 0e435d604821..f443e76d6779 100644 --- a/scripts/ci/gitlab/pipeline/check.yml +++ b/scripts/ci/gitlab/pipeline/check.yml @@ -51,8 +51,8 @@ check-try-runtime: - cargo check --features try-runtime --all # More info can be found here: https://github.com/paritytech/polkadot/pull/5865 -# Works only in PRs -check-runtime-migration: +# Works only in PRs with E1 label +.check-runtime-migration: stage: check extends: - .docker-env @@ -67,10 +67,41 @@ check-runtime-migration: if [[ $has_runtimemigration_label != 0 ]]; then echo "Found label runtimemigration. Running tests" export RUST_LOG=remote-ext=debug,runtime=debug - time cargo test --release -p westend-runtime -p polkadot-runtime -p kusama-runtime --features try-runtime + echo "---------- Running try-runtime for ${NETWORK} ----------" + time cargo run --release --features=try-runtime try-runtime --chain=${NETWORK}-dev --execution=Wasm --no-spec-check-panic on-runtime-upgrade live --uri wss://${NETWORK}-try-runtime-node.parity-chains.parity.io:443 else echo "runtimemigration label not found. Skipping" fi + +check-runtime-migration-polkadot: + stage: check + extends: + - .docker-env + - .test-pr-refs + - .compiler-info + - .check-runtime-migration + variables: + NETWORK: "polkadot" + +check-runtime-migration-kusama: + stage: check + extends: + - .docker-env + - .test-pr-refs + - .compiler-info + - .check-runtime-migration + variables: + NETWORK: "kusama" + +check-runtime-migration-westend: + stage: check + extends: + - .docker-env + - .test-pr-refs + - .compiler-info + - .check-runtime-migration + variables: + NETWORK: "westend" allow_failure: true # is broken, need to fix diff --git a/scripts/ci/gitlab/pipeline/publish.yml b/scripts/ci/gitlab/pipeline/publish.yml index 12e087e188d1..3484fcae336e 100644 --- a/scripts/ci/gitlab/pipeline/publish.yml +++ b/scripts/ci/gitlab/pipeline/publish.yml @@ -7,6 +7,7 @@ publish-polkadot-debug-image: stage: publish extends: + - .kubernetes-env - .build-push-image rules: # Don't run when triggered from another pipeline @@ -18,6 +19,7 @@ publish-polkadot-debug-image: - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1 variables: + CI_IMAGE: ${BUILDAH_IMAGE} GIT_STRATEGY: none DOCKER_USER: ${PARITYPR_USER} DOCKER_PASS: ${PARITYPR_PASS} @@ -42,9 +44,11 @@ publish-test-collators-image: # service image for Simnet stage: publish extends: + - .kubernetes-env - .build-push-image - .zombienet-refs variables: + CI_IMAGE: ${BUILDAH_IMAGE} GIT_STRATEGY: none DOCKER_USER: ${PARITYPR_USER} DOCKER_PASS: ${PARITYPR_PASS} @@ -68,9 +72,11 @@ publish-malus-image: # service image for Simnet stage: publish extends: + - .kubernetes-env - .build-push-image - .zombienet-refs variables: + CI_IMAGE: ${BUILDAH_IMAGE} GIT_STRATEGY: none DOCKER_USER: ${PARITYPR_USER} DOCKER_PASS: ${PARITYPR_PASS} @@ -93,9 +99,11 @@ publish-malus-image: publish-staking-miner-image: stage: publish extends: + - .kubernetes-env - .build-push-image - .publish-refs variables: + CI_IMAGE: ${BUILDAH_IMAGE} # scripts/ci/dockerfiles/staking-miner/staking-miner_injected.Dockerfile DOCKERFILE: ci/dockerfiles/staking-miner/staking-miner_injected.Dockerfile IMAGE_NAME: docker.io/paritytech/staking-miner @@ -114,8 +122,8 @@ publish-s3-release: needs: - job: build-linux-stable artifacts: true - image: paritytech/awscli:latest variables: + CI_IMAGE: paritytech/awscli:latest GIT_STRATEGY: none PREFIX: "builds/polkadot/${ARCH}-${DOCKER_OS}" rules: @@ -152,9 +160,8 @@ publish-rustdoc: stage: publish extends: - .kubernetes-env - image: paritytech/tools:latest variables: - GIT_DEPTH: 100 + CI_IMAGE: paritytech/tools:latest rules: - if: $CI_PIPELINE_SOURCE == "pipeline" when: never diff --git a/scripts/ci/gitlab/pipeline/test.yml b/scripts/ci/gitlab/pipeline/test.yml index 9a3dd0270fbb..3a21a77d90f2 100644 --- a/scripts/ci/gitlab/pipeline/test.yml +++ b/scripts/ci/gitlab/pipeline/test.yml @@ -72,3 +72,18 @@ test-deterministic-wasm: - .compiler-info script: - ./scripts/ci/gitlab/test_deterministic_wasm.sh + +cargo-clippy: + stage: test + # this is an artificial job dependency, for pipeline optimization using GitLab's DAGs + # the job can be found in check.yml + needs: + - job: job-starter + artifacts: false + variables: + RUSTY_CACHIER_TOOLCHAIN: nightly + extends: + - .docker-env + - .test-refs + script: + - SKIP_WASM_BUILD=1 env -u RUSTFLAGS cargo +nightly clippy --all-targets diff --git a/scripts/ci/gitlab/pipeline/zombienet.yml b/scripts/ci/gitlab/pipeline/zombienet.yml index 5c6215aad2c4..b088f20c55ff 100644 --- a/scripts/ci/gitlab/pipeline/zombienet.yml +++ b/scripts/ci/gitlab/pipeline/zombienet.yml @@ -202,8 +202,7 @@ zombienet-tests-misc-upgrade-node: - echo "${PARACHAINS_IMAGE_NAME} ${PARACHAINS_IMAGE_TAG}" - echo "${GH_DIR}" - export DEBUG=zombie,zombie::network-node - - BUILD_RELEASE_VERSION="$(cat ./artifacts/BUILD_RELEASE_VERSION)" - - export ZOMBIENET_INTEGRATION_TEST_IMAGE="docker.io/parity/polkadot:${BUILD_RELEASE_VERSION}" + - export ZOMBIENET_INTEGRATION_TEST_IMAGE="docker.io/parity/polkadot:latest" - export COL_IMAGE=${COLLATOR_IMAGE_NAME}:${COLLATOR_IMAGE_TAG} - BUILD_LINUX_JOB_ID="$(cat ./artifacts/BUILD_LINUX_JOB_ID)" - export POLKADOT_PR_BIN_URL="https://gitlab.parity.io/parity/mirrors/polkadot/-/jobs/${BUILD_LINUX_JOB_ID}/artifacts/raw/artifacts/polkadot" diff --git a/src/main.rs b/src/main.rs index 14d62fbb9ad6..13c17df851f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,11 @@ use color_eyre::eyre; +/// Global allocator. Changing it to another allocator will require changing +/// `memory_stats::MemoryAllocationTracker`. +#[global_allocator] +pub static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; + fn main() -> eyre::Result<()> { color_eyre::install()?; polkadot_cli::run()?; diff --git a/statement-table/Cargo.toml b/statement-table/Cargo.toml index d61f4110825d..464cabb49650 100644 --- a/statement-table/Cargo.toml +++ b/statement-table/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "polkadot-statement-table" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } primitives = { package = "polkadot-primitives", path = "../primitives" } diff --git a/tests/benchmark_block.rs b/tests/benchmark_block.rs index ee68d43b2aa5..dc3b174599a9 100644 --- a/tests/benchmark_block.rs +++ b/tests/benchmark_block.rs @@ -32,7 +32,7 @@ use tempfile::tempdir; pub mod common; -static RUNTIMES: [&'static str; 4] = ["polkadot", "kusama", "westend", "rococo"]; +static RUNTIMES: [&str; 4] = ["polkadot", "kusama", "westend", "rococo"]; /// `benchmark block` works for all dev runtimes using the wasm executor. #[tokio::test] @@ -54,7 +54,7 @@ async fn build_chain(runtime: &str, base_path: &Path) -> Result<(), String> { let mut cmd = Command::new(cargo_bin("polkadot")) .stdout(process::Stdio::piped()) .stderr(process::Stdio::piped()) - .args(["--chain", &runtime, "--force-authoring", "--alice"]) + .args(["--chain", runtime, "--force-authoring", "--alice"]) .arg("-d") .arg(base_path) .arg("--no-hardware-benchmarks") @@ -77,7 +77,7 @@ async fn build_chain(runtime: &str, base_path: &Path) -> Result<(), String> { fn benchmark_block(runtime: &str, base_path: &Path, block: u32) -> Result<(), String> { // Invoke `benchmark block` with all options to make sure that they are valid. let status = Command::new(cargo_bin("polkadot")) - .args(["benchmark", "block", "--chain", &runtime]) + .args(["benchmark", "block", "--chain", runtime]) .arg("-d") .arg(base_path) .args(["--from", &block.to_string(), "--to", &block.to_string()]) diff --git a/tests/benchmark_extrinsic.rs b/tests/benchmark_extrinsic.rs index c112a8c023f8..79a7d4c45322 100644 --- a/tests/benchmark_extrinsic.rs +++ b/tests/benchmark_extrinsic.rs @@ -17,10 +17,9 @@ use assert_cmd::cargo::cargo_bin; use std::{process::Command, result::Result}; -static RUNTIMES: [&'static str; 4] = ["polkadot", "kusama", "westend", "rococo"]; +static RUNTIMES: [&str; 4] = ["polkadot", "kusama", "westend", "rococo"]; -static EXTRINSICS: [(&'static str, &'static str); 2] = - [("system", "remark"), ("balances", "transfer_keep_alive")]; +static EXTRINSICS: [(&str, &str); 2] = [("system", "remark"), ("balances", "transfer_keep_alive")]; /// `benchmark extrinsic` works for all dev runtimes and some extrinsics. #[test] @@ -43,8 +42,8 @@ fn benchmark_extrinsic_rejects_non_dev_runtimes() { fn benchmark_extrinsic(runtime: &str, pallet: &str, extrinsic: &str) -> Result<(), String> { let status = Command::new(cargo_bin("polkadot")) - .args(["benchmark", "extrinsic", "--chain", &runtime]) - .args(&["--pallet", pallet, "--extrinsic", extrinsic]) + .args(["benchmark", "extrinsic", "--chain", runtime]) + .args(["--pallet", pallet, "--extrinsic", extrinsic]) // Run with low repeats for faster execution. .args(["--repeat=1", "--warmup=1", "--max-ext-per-block=1"]) .status() diff --git a/tests/benchmark_overhead.rs b/tests/benchmark_overhead.rs index a3b4ed1160ea..10582870168e 100644 --- a/tests/benchmark_overhead.rs +++ b/tests/benchmark_overhead.rs @@ -18,7 +18,7 @@ use assert_cmd::cargo::cargo_bin; use std::{process::Command, result::Result}; use tempfile::tempdir; -static RUNTIMES: [&'static str; 4] = ["polkadot", "kusama", "westend", "rococo"]; +static RUNTIMES: [&str; 4] = ["polkadot", "kusama", "westend", "rococo"]; /// `benchmark overhead` works for all dev runtimes. #[test] diff --git a/tests/benchmark_storage_works.rs b/tests/benchmark_storage_works.rs index f5e2851f250f..7c9e40b9d0b9 100644 --- a/tests/benchmark_storage_works.rs +++ b/tests/benchmark_storage_works.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +#![cfg(feature = "runtime-benchmarks")] + use assert_cmd::cargo::cargo_bin; use std::{ path::Path, @@ -38,7 +40,7 @@ fn benchmark_storage_works() { /// Invoke the `benchmark storage` sub-command. fn benchmark_storage(db: &str, base_path: &Path) -> ExitStatus { Command::new(cargo_bin("polkadot")) - .args(&["benchmark", "storage", "--dev"]) + .args(["benchmark", "storage", "--dev"]) .arg("--db") .arg(db) .arg("--weight-path") diff --git a/tests/common.rs b/tests/common.rs index 3f040208972c..6a41975f87fa 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -91,11 +91,13 @@ pub fn find_ws_url_from_output(read: impl Read + Send) -> (String, String) { // does the line contain our port (we expect this specific output from substrate). let sock_addr = match line.split_once("Running JSON-RPC WS server: addr=") { None => return None, - Some((_, after)) => after.split_once(",").unwrap().0, + Some((_, after)) => after.split_once(',').unwrap().0, }; Some(format!("ws://{}", sock_addr)) }) - .expect(&format!("Could not find WebSocket address in process output:\n{}", &data)); + .unwrap_or_else(|| { + panic!("Could not find WebSocket address in process output:\n{}", &data) + }); (ws_url, data) } diff --git a/tests/invalid_order_arguments.rs b/tests/invalid_order_arguments.rs index f205e935ab95..f8dc32a82a26 100644 --- a/tests/invalid_order_arguments.rs +++ b/tests/invalid_order_arguments.rs @@ -24,7 +24,7 @@ fn invalid_order_arguments() { let tmpdir = tempdir().expect("could not create temp dir"); let status = Command::new(cargo_bin("polkadot")) - .args(&["--dev", "invalid_order_arguments", "-d"]) + .args(["--dev", "invalid_order_arguments", "-d"]) .arg(tmpdir.path()) .arg("-y") .status() diff --git a/tests/purge_chain_works.rs b/tests/purge_chain_works.rs index c69d8cc4a81a..ab3ee506b60a 100644 --- a/tests/purge_chain_works.rs +++ b/tests/purge_chain_works.rs @@ -36,7 +36,7 @@ async fn purge_chain_rocksdb_works() { let mut cmd = Command::new(cargo_bin("polkadot")) .stdout(process::Stdio::piped()) .stderr(process::Stdio::piped()) - .args(&["--dev", "-d"]) + .args(["--dev", "-d"]) .arg(tmpdir.path()) .arg("--port") .arg("33034") @@ -61,7 +61,7 @@ async fn purge_chain_rocksdb_works() { // Purge chain let status = Command::new(cargo_bin("polkadot")) - .args(&["purge-chain", "--dev", "-d"]) + .args(["purge-chain", "--dev", "-d"]) .arg(tmpdir.path()) .arg("-y") .status() @@ -86,7 +86,7 @@ async fn purge_chain_paritydb_works() { let mut cmd = Command::new(cargo_bin("polkadot")) .stdout(process::Stdio::piped()) .stderr(process::Stdio::piped()) - .args(&["--dev", "-d"]) + .args(["--dev", "-d"]) .arg(tmpdir.path()) .arg("--database") .arg("paritydb-experimental") @@ -111,7 +111,7 @@ async fn purge_chain_paritydb_works() { // Purge chain let status = Command::new(cargo_bin("polkadot")) - .args(&["purge-chain", "--dev", "-d"]) + .args(["purge-chain", "--dev", "-d"]) .arg(tmpdir.path()) .arg("--database") .arg("paritydb-experimental") diff --git a/tests/running_the_node_and_interrupt.rs b/tests/running_the_node_and_interrupt.rs index 895db534bc5c..5b0e6ec8b013 100644 --- a/tests/running_the_node_and_interrupt.rs +++ b/tests/running_the_node_and_interrupt.rs @@ -40,7 +40,7 @@ async fn running_the_node_works_and_can_be_interrupted() { let mut cmd = Command::new(cargo_bin("polkadot")) .stdout(process::Stdio::piped()) .stderr(process::Stdio::piped()) - .args(&["--dev", "-d"]) + .args(["--dev", "-d"]) .arg(tmpdir.path()) .arg("--no-hardware-benchmarks") .spawn() diff --git a/utils/generate-bags/Cargo.toml b/utils/generate-bags/Cargo.toml index 387f35f4e614..8eb6c81f2306 100644 --- a/utils/generate-bags/Cargo.toml +++ b/utils/generate-bags/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "polkadot-voter-bags" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] clap = { version = "4.0.9", features = ["derive"] } -generate-bags = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +generate-bags = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } westend-runtime = { path = "../../runtime/westend" } kusama-runtime = { path = "../../runtime/kusama" } diff --git a/utils/remote-ext-tests/bags-list/Cargo.toml b/utils/remote-ext-tests/bags-list/Cargo.toml index a81a0eccc26e..a7c76bd9b511 100644 --- a/utils/remote-ext-tests/bags-list/Cargo.toml +++ b/utils/remote-ext-tests/bags-list/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "remote-ext-tests-bags-list" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] polkadot-runtime = { path = "../../../runtime/polkadot" } @@ -12,11 +12,11 @@ polkadot-runtime-constants = { path = "../../../runtime/polkadot/constants" } kusama-runtime-constants = { path = "../../../runtime/kusama/constants" } westend-runtime-constants = { path = "../../../runtime/westend/constants" } -pallet-bags-list-remote-tests = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +pallet-bags-list-remote-tests = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } clap = { version = "4.0.9", features = ["derive"] } log = "0.4.17" -tokio = { version = "1.19.2", features = ["macros"] } +tokio = { version = "1.22.0", features = ["macros"] } diff --git a/utils/staking-miner/Cargo.toml b/utils/staking-miner/Cargo.toml index a0aecbc09add..aa4c2aef5299 100644 --- a/utils/staking-miner/Cargo.toml +++ b/utils/staking-miner/Cargo.toml @@ -1,36 +1,36 @@ [package] name = "staking-miner" -version = "0.9.31" -authors = ["Parity Technologies "] -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } clap = { version = "4.0.9", features = ["derive", "env"] } tracing-subscriber = { version = "0.3.11", features = ["env-filter"] } -jsonrpsee = { version = "0.15.1", features = ["ws-client", "macros"] } +jsonrpsee = { version = "0.16.2", features = ["ws-client", "macros"] } log = "0.4.17" paste = "1.0.7" serde = "1.0.137" serde_json = "1.0" thiserror = "1.0.31" -tokio = { version = "1.19.2", features = ["macros", "rt-multi-thread", "sync"] } -remote-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +tokio = { version = "1.22.0", features = ["macros", "rt-multi-thread", "sync"] } +remote-externalities = { git = "https://github.com/paritytech/substrate", package = "frame-remote-externalities" , branch = "polkadot-v0.9.36" } signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-npos-elections = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-npos-elections = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-election-provider-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-election-provider-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } core-primitives = { package = "polkadot-core-primitives", path = "../../core-primitives" } diff --git a/utils/staking-miner/src/emergency_solution.rs b/utils/staking-miner/src/emergency_solution.rs index cbf86af4c1d0..fdb3a47a270d 100644 --- a/utils/staking-miner/src/emergency_solution.rs +++ b/utils/staking-miner/src/emergency_solution.rs @@ -36,21 +36,23 @@ macro_rules! emergency_solution_cmd_for { ($runtime:ident) => { paste::paste! { log::info!(target: LOG_TARGET, "mined solution with {:?}", &raw_solution.score); - let mut ready_solution = EPM::Pallet::::feasibility_check(raw_solution, EPM::ElectionCompute::Signed)?; - + let ready_solution = EPM::Pallet::::feasibility_check(raw_solution, EPM::ElectionCompute::Signed)?; + let encoded_size = ready_solution.encoded_size(); + let score = ready_solution.score; + let mut supports = ready_solution.supports.into_inner(); // maybe truncate. if let Some(take) = config.take { - log::info!(target: LOG_TARGET, "truncating {} winners to {}", ready_solution.supports.len(), take); - ready_solution.supports.sort_unstable_by_key(|(_, s)| s.total); - ready_solution.supports.truncate(take); + log::info!(target: LOG_TARGET, "truncating {} winners to {}", supports.len(), take); + supports.sort_unstable_by_key(|(_, s)| s.total); + supports.truncate(take); } // write to file and stdout. - let encoded_support = ready_solution.supports.encode(); + let encoded_support = supports.encode(); let mut supports_file = std::fs::File::create("solution.supports.bin")?; supports_file.write_all(&encoded_support)?; - log::info!(target: LOG_TARGET, "ReadySolution: size {:?} / score = {:?}", ready_solution.encoded_size(), ready_solution.score); + log::info!(target: LOG_TARGET, "ReadySolution: size {:?} / score = {:?}", encoded_size, score); log::trace!(target: LOG_TARGET, "Supports: {}", sp_core::hexdisplay::HexDisplay::from(&encoded_support)); Ok(()) diff --git a/utils/staking-miner/src/main.rs b/utils/staking-miner/src/main.rs index 4a7784f371e0..84c57bc6d2e8 100644 --- a/utils/staking-miner/src/main.rs +++ b/utils/staking-miner/src/main.rs @@ -302,7 +302,7 @@ async fn create_election_ext( ) -> Result> where T: EPM::Config, - B: BlockT, + B: BlockT + DeserializeOwned, B::Header: DeserializeOwned, { use frame_support::{storage::generator::StorageMap, traits::PalletInfo}; @@ -317,13 +317,14 @@ where transport: client.into_inner().into(), at, pallets, + hashed_prefixes: vec![>::prefix_hash()], + hashed_keys: vec![[twox_128(b"System"), twox_128(b"Number")].concat()], ..Default::default() })) - .inject_hashed_prefix(&>::prefix_hash()) - .inject_hashed_key(&[twox_128(b"System"), twox_128(b"Number")].concat()) .build() .await .map_err(|why| Error::RemoteExternalities(why)) + .map(|rx| rx.inner_ext) } /// Compute the election. It expects to NOT be `Phase::Off`. In other words, the snapshot must @@ -425,6 +426,7 @@ fn mine_dpos(ext: &mut Ext) -> Result<(), Error> { pub(crate) async fn check_versions( rpc: &SharedRpcClient, + print: bool, ) -> Result<(), Error> { let linked_version = T::Version::get(); let on_chain_version = rpc @@ -432,10 +434,31 @@ pub(crate) async fn check_versions( .await .expect("runtime version RPC should always work; qed"); - log::debug!(target: LOG_TARGET, "linked version {:?}", linked_version); - log::debug!(target: LOG_TARGET, "on-chain version {:?}", on_chain_version); + let do_print = || { + log::info!( + target: LOG_TARGET, + "linked version {:?}", + (&linked_version.spec_name, &linked_version.spec_version) + ); + log::info!( + target: LOG_TARGET, + "on-chain version {:?}", + (&on_chain_version.spec_name, &on_chain_version.spec_version) + ); + }; + + if print { + do_print(); + } - if linked_version != on_chain_version { + // we relax the checking here a bit, which should not cause any issues in production (a chain + // that messes up its spec name is highly unlikely), but it allows us to do easier testing. + if linked_version.spec_name != on_chain_version.spec_name || + linked_version.spec_version != on_chain_version.spec_version + { + if !print { + do_print(); + } log::error!( target: LOG_TARGET, "VERSION MISMATCH: any transaction will fail with bad-proof" @@ -563,7 +586,7 @@ async fn main() { log::info!(target: LOG_TARGET, "connected to chain {:?}", chain); any_runtime_unit! { - check_versions::(&rpc).await + check_versions::(&rpc, true).await }; let outcome = any_runtime! { diff --git a/utils/staking-miner/src/monitor.rs b/utils/staking-miner/src/monitor.rs index 30f1b2ded908..bfc075668e66 100644 --- a/utils/staking-miner/src/monitor.rs +++ b/utils/staking-miner/src/monitor.rs @@ -64,7 +64,7 @@ where .map_err::, _>(Into::into)? .unwrap_or_default(); - for (_score, idx) in indices { + for (_score, _bn, idx) in indices { let key = StorageKey(EPM::SignedSubmissionsMap::::hashed_key_for(idx)); if let Some(submission) = rpc @@ -81,20 +81,36 @@ where Ok(()) } +/// `true` if `our_score` should pass the onchain `best_score` with the given strategy. +pub(crate) fn score_passes_strategy( + our_score: sp_npos_elections::ElectionScore, + best_score: sp_npos_elections::ElectionScore, + strategy: SubmissionStrategy, +) -> bool { + match strategy { + SubmissionStrategy::Always => true, + SubmissionStrategy::IfLeading => + our_score == best_score || + our_score.strict_threshold_better(best_score, Perbill::zero()), + SubmissionStrategy::ClaimBetterThan(epsilon) => + our_score.strict_threshold_better(best_score, epsilon), + SubmissionStrategy::ClaimNoWorseThan(epsilon) => + !best_score.strict_threshold_better(our_score, epsilon), + } +} + /// Reads all current solutions and checks the scores according to the `SubmissionStrategy`. -async fn ensure_no_better_solution( +async fn ensure_strategy_met( rpc: &SharedRpcClient, at: Hash, score: sp_npos_elections::ElectionScore, strategy: SubmissionStrategy, max_submissions: u32, ) -> Result<(), Error> { - let epsilon = match strategy { - // don't care about current scores. - SubmissionStrategy::Always => return Ok(()), - SubmissionStrategy::IfLeading => Perbill::zero(), - SubmissionStrategy::ClaimBetterThan(epsilon) => epsilon, - }; + // don't care about current scores. + if matches!(strategy, SubmissionStrategy::Always) { + return Ok(()) + } let indices_key = StorageKey(EPM::SignedSubmissionIndices::::hashed_key().to_vec()); @@ -104,34 +120,15 @@ async fn ensure_no_better_solution( .map_err::, _>(Into::into)? .unwrap_or_default(); - let mut is_best_score = true; - let mut scores = 0; - - log::debug!(target: LOG_TARGET, "submitted solutions on chain: {:?}", indices); - - // BTreeMap is ordered, take last to get the max score. - for (curr_max_score, _) in indices.into_iter() { - if !score.strict_threshold_better(curr_max_score, epsilon) { - log::warn!(target: LOG_TARGET, "mined score is not better; skipping to submit"); - is_best_score = false; - } - - if score == curr_max_score { - log::warn!( - target: LOG_TARGET, - "mined score has the same score as already submitted score" - ); - } - - // Indices can't be bigger than u32::MAX so can't overflow. - scores += 1; + if indices.len() >= max_submissions as usize { + log::debug!(target: LOG_TARGET, "The submissions queue is full"); } - if scores == max_submissions { - log::warn!(target: LOG_TARGET, "The submissions queue is full"); - } + // default score is all zeros, any score is better than it. + let best_score = indices.last().map(|(score, _, _)| *score).unwrap_or_default(); + log::debug!(target: LOG_TARGET, "best onchain score is {:?}", best_score); - if is_best_score { + if score_passes_strategy(score, best_score, strategy) { Ok(()) } else { Err(Error::StrategyNotSatisfied) @@ -233,7 +230,7 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! { // block on this because if this fails there is no way to recover from // that error i.e, upgrade/downgrade required. - if let Err(err) = crate::check_versions::(&rpc).await { + if let Err(err) = crate::check_versions::(&rpc, false).await { let _ = tx.send(err.into()); return; } @@ -314,9 +311,14 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! { } }; - let ensure_no_better_fut = tokio::spawn(async move { - ensure_no_better_solution::(&rpc1, latest_head, score, config.submission_strategy, - SignedMaxSubmissions::get()).await + let ensure_strategy_met_fut = tokio::spawn(async move { + ensure_strategy_met::( + &rpc1, + latest_head, + score, + config.submission_strategy, + SignedMaxSubmissions::get() + ).await }); let ensure_signed_phase_fut = tokio::spawn(async move { @@ -325,7 +327,7 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! { // Run the calls in parallel and return once all has completed or any failed. if let Err(err) = tokio::try_join!( - flatten(ensure_no_better_fut), + flatten(ensure_strategy_met_fut), flatten(ensure_signed_phase_fut), ) { log::debug!(target: LOG_TARGET, "Skipping to submit at block {}; {}", at.number, err); @@ -420,3 +422,46 @@ macro_rules! monitor_cmd_for { ($runtime:tt) => { paste::paste! { monitor_cmd_for!(polkadot); monitor_cmd_for!(kusama); monitor_cmd_for!(westend); + +#[cfg(test)] +pub mod tests { + use super::*; + + #[test] + fn score_passes_strategy_works() { + let s = |x| sp_npos_elections::ElectionScore { minimal_stake: x, ..Default::default() }; + let two = Perbill::from_percent(2); + + // anything passes Always + assert!(score_passes_strategy(s(0), s(0), SubmissionStrategy::Always)); + assert!(score_passes_strategy(s(5), s(0), SubmissionStrategy::Always)); + assert!(score_passes_strategy(s(5), s(10), SubmissionStrategy::Always)); + + // if leading + assert!(score_passes_strategy(s(0), s(0), SubmissionStrategy::IfLeading)); + assert!(score_passes_strategy(s(1), s(0), SubmissionStrategy::IfLeading)); + assert!(score_passes_strategy(s(2), s(0), SubmissionStrategy::IfLeading)); + assert!(!score_passes_strategy(s(5), s(10), SubmissionStrategy::IfLeading)); + assert!(!score_passes_strategy(s(9), s(10), SubmissionStrategy::IfLeading)); + assert!(score_passes_strategy(s(10), s(10), SubmissionStrategy::IfLeading)); + + // if better by 2% + assert!(!score_passes_strategy(s(50), s(100), SubmissionStrategy::ClaimBetterThan(two))); + assert!(!score_passes_strategy(s(100), s(100), SubmissionStrategy::ClaimBetterThan(two))); + assert!(!score_passes_strategy(s(101), s(100), SubmissionStrategy::ClaimBetterThan(two))); + assert!(!score_passes_strategy(s(102), s(100), SubmissionStrategy::ClaimBetterThan(two))); + assert!(score_passes_strategy(s(103), s(100), SubmissionStrategy::ClaimBetterThan(two))); + assert!(score_passes_strategy(s(150), s(100), SubmissionStrategy::ClaimBetterThan(two))); + + // if no less than 2% worse + assert!(!score_passes_strategy(s(50), s(100), SubmissionStrategy::ClaimNoWorseThan(two))); + assert!(!score_passes_strategy(s(97), s(100), SubmissionStrategy::ClaimNoWorseThan(two))); + assert!(score_passes_strategy(s(98), s(100), SubmissionStrategy::ClaimNoWorseThan(two))); + assert!(score_passes_strategy(s(99), s(100), SubmissionStrategy::ClaimNoWorseThan(two))); + assert!(score_passes_strategy(s(100), s(100), SubmissionStrategy::ClaimNoWorseThan(two))); + assert!(score_passes_strategy(s(101), s(100), SubmissionStrategy::ClaimNoWorseThan(two))); + assert!(score_passes_strategy(s(102), s(100), SubmissionStrategy::ClaimNoWorseThan(two))); + assert!(score_passes_strategy(s(103), s(100), SubmissionStrategy::ClaimNoWorseThan(two))); + assert!(score_passes_strategy(s(150), s(100), SubmissionStrategy::ClaimNoWorseThan(two))); + } +} diff --git a/utils/staking-miner/src/opts.rs b/utils/staking-miner/src/opts.rs index 0a6c50cda90a..d7690a21205b 100644 --- a/utils/staking-miner/src/opts.rs +++ b/utils/staking-miner/src/opts.rs @@ -89,7 +89,9 @@ pub(crate) struct MonitorConfig { /// `--submission-strategy always`: always submit. /// /// `--submission-strategy "percent-better "`: submit if the submission is `n` percent better. - #[arg(long, default_value = "if-leading")] + /// + /// `--submission-strategy "no-worse-than "`: submit if submission is no more than `n` percent worse. + #[clap(long, default_value = "if-leading")] pub submission_strategy: SubmissionStrategy, /// Delay in number seconds to wait until starting mining a solution. @@ -157,12 +159,14 @@ pub(crate) struct InfoOpts { #[derive(Debug, Copy, Clone)] #[cfg_attr(test, derive(PartialEq))] pub enum SubmissionStrategy { - // Only submit if at the time, we are the best. - IfLeading, - // Always submit. + /// Always submit. Always, - // Submit if we are leading, or if the solution that's leading is more that the given `Perbill` - // better than us. This helps detect obviously fake solutions and still combat them. + /// Only submit if at the time, we are the best (or equal to it). + IfLeading, + /// Submit if we are no worse than `Perbill` worse than the best. + ClaimNoWorseThan(Perbill), + /// Submit if we are leading, or if the solution that's leading is more that the given `Perbill` + /// better than us. This helps detect obviously fake solutions and still combat them. ClaimBetterThan(Perbill), } @@ -185,6 +189,7 @@ pub(crate) enum Solver { /// * --submission-strategy if-leading: only submit if leading /// * --submission-strategy always: always submit /// * --submission-strategy "percent-better ": submit if submission is `n` percent better. +/// * --submission-strategy "no-worse-than": submit if submission is no more than `n` percent worse. /// impl FromStr for SubmissionStrategy { type Err = String; @@ -196,8 +201,11 @@ impl FromStr for SubmissionStrategy { Self::IfLeading } else if s == "always" { Self::Always - } else if s.starts_with("percent-better ") { - let percent: u32 = s[15..].parse().map_err(|e| format!("{:?}", e))?; + } else if let Some(percent) = s.strip_prefix("no-worse-than ") { + let percent: u32 = percent.parse().map_err(|e| format!("{:?}", e))?; + Self::ClaimNoWorseThan(Perbill::from_percent(percent)) + } else if let Some(percent) = s.strip_prefix("percent-better ") { + let percent: u32 = percent.parse().map_err(|e| format!("{:?}", e))?; Self::ClaimBetterThan(Perbill::from_percent(percent)) } else { return Err(s.into()) diff --git a/xcm/Cargo.toml b/xcm/Cargo.toml index f08fc209489f..e58e1bb7c701 100644 --- a/xcm/Cargo.toml +++ b/xcm/Cargo.toml @@ -1,15 +1,15 @@ [package] name = "xcm" -version = "0.9.31" -authors = ["Parity Technologies "] description = "The basic XCM datastructures." -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] impl-trait-for-tuples = "0.2.2" parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } derivative = {version = "2.2.0", default-features = false, features = [ "use_core" ] } log = { version = "0.4.17", default-features = false } xcm-procedural = { path = "procedural" } diff --git a/xcm/pallet-xcm-benchmarks/Cargo.toml b/xcm/pallet-xcm-benchmarks/Cargo.toml index 2610f04859c5..dd5f343a8f88 100644 --- a/xcm/pallet-xcm-benchmarks/Cargo.toml +++ b/xcm/pallet-xcm-benchmarks/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "pallet-xcm-benchmarks" -authors = ["Parity Technologies "] -edition = "2021" -version = "0.9.31" +authors.workspace = true +edition.workspace = true +version.workspace = true [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] @@ -10,21 +10,21 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } xcm-executor = { path = "../xcm-executor", default-features = false } -frame-benchmarking = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } +frame-benchmarking = { default-features = false, git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } xcm = { path = "..", default-features = false } log = "0.4.17" [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } -pallet-assets = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } -sp-tracing = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.31" } +pallet-balances = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } +pallet-assets = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } +sp-tracing = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.36" } xcm-builder = { path = "../xcm-builder" } xcm = { path = ".." } # temp diff --git a/xcm/pallet-xcm/Cargo.toml b/xcm/pallet-xcm/Cargo.toml index 83e8c7e4d1d7..54fd4ef30214 100644 --- a/xcm/pallet-xcm/Cargo.toml +++ b/xcm/pallet-xcm/Cargo.toml @@ -1,8 +1,9 @@ [package] -authors = ["Parity Technologies "] -edition = "2021" name = "pallet-xcm" -version = "0.9.31" +authors.workspace = true +edition.workspace = true +version.workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } @@ -10,19 +11,19 @@ scale-info = { version = "2.1.2", default-features = false, features = ["derive" serde = { version = "1.0.137", optional = true, features = ["derive"] } log = { version = "0.4.17", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.31" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.31" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.36" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.36" } xcm = { path = "..", default-features = false } xcm-executor = { path = "../xcm-executor", default-features = false } [dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } polkadot-runtime-parachains = { path = "../../runtime/parachains" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } xcm-builder = { path = "../xcm-builder" } polkadot-parachain = { path = "../../parachain" } diff --git a/xcm/pallet-xcm/src/tests.rs b/xcm/pallet-xcm/src/tests.rs index b619efefbe9b..6da02cf10cf6 100644 --- a/xcm/pallet-xcm/src/tests.rs +++ b/xcm/pallet-xcm/src/tests.rs @@ -270,7 +270,7 @@ fn teleport_assets_works() { /// Asserts that the sender's balance is decreased as a result of execution of /// local effects. #[test] -fn limmited_teleport_assets_works() { +fn limited_teleport_assets_works() { let balances = vec![ (ALICE, INITIAL_BALANCE), (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), @@ -314,7 +314,7 @@ fn limmited_teleport_assets_works() { /// Asserts that the sender's balance is decreased as a result of execution of /// local effects. #[test] -fn unlimmited_teleport_assets_works() { +fn unlimited_teleport_assets_works() { let balances = vec![ (ALICE, INITIAL_BALANCE), (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), diff --git a/xcm/procedural/Cargo.toml b/xcm/procedural/Cargo.toml index 14a7d068db68..22ec39077c97 100644 --- a/xcm/procedural/Cargo.toml +++ b/xcm/procedural/Cargo.toml @@ -1,8 +1,8 @@ [package] -authors = ["Parity Technologies "] name = "xcm-procedural" -version = "0.9.31" -edition = "2021" +authors.workspace = true +edition.workspace = true +version.workspace = true [lib] proc-macro = true diff --git a/xcm/src/v0/multi_location.rs b/xcm/src/v0/multi_location.rs index 0491e27d644f..1bf49ad841a6 100644 --- a/xcm/src/v0/multi_location.rs +++ b/xcm/src/v0/multi_location.rs @@ -356,17 +356,30 @@ impl MultiLocation { /// # } /// ``` pub fn match_and_split(&self, prefix: &MultiLocation) -> Option<&Junction> { - if prefix.len() + 1 != self.len() { + if prefix.len() + 1 != self.len() || !self.starts_with(prefix) { return None } - for i in 0..prefix.len() { - if prefix.at(i) != self.at(i) { - return None - } - } return self.at(prefix.len()) } + /// Returns whether `self` begins with or is equal to `prefix`. + /// + /// # Example + /// ```rust + /// # use xcm::v0::{Junction::*, MultiLocation::*}; + /// let m = X4(Parent, PalletInstance(3), OnlyChild, OnlyChild); + /// assert!(m.starts_with(&X2(Parent, PalletInstance(3)))); + /// assert!(m.starts_with(&m)); + /// assert!(!m.starts_with(&X2(Parent, GeneralIndex(99)))); + /// assert!(!m.starts_with(&X1(PalletInstance(3)))); + /// ``` + pub fn starts_with(&self, prefix: &MultiLocation) -> bool { + if self.len() < prefix.len() { + return false + } + prefix.iter().zip(self.iter()).all(|(l, r)| l == r) + } + /// Mutates `self`, suffixing it with `new`. Returns `Err` in case of overflow. pub fn push(&mut self, new: Junction) -> result::Result<(), ()> { let mut n = MultiLocation::Null; @@ -601,6 +614,24 @@ mod tests { assert_eq!(m.match_and_split(&m), None); } + #[test] + fn starts_with_works() { + let full = X3(Parent, Parachain(1000), AccountIndex64 { network: Any, index: 23 }); + let identity = full.clone(); + let prefix = X2(Parent, Parachain(1000)); + let wrong_parachain = X2(Parent, Parachain(1001)); + let wrong_account = X3(Parent, Parachain(1000), AccountIndex64 { network: Any, index: 24 }); + let no_parents = X1(Parachain(1000)); + let too_many_parents = X3(Parent, Parent, Parachain(1000)); + + assert!(full.starts_with(&identity)); + assert!(full.starts_with(&prefix)); + assert!(!full.starts_with(&wrong_parachain)); + assert!(!full.starts_with(&wrong_account)); + assert!(!full.starts_with(&no_parents)); + assert!(!full.starts_with(&too_many_parents)); + } + #[test] fn append_with_works() { let acc = AccountIndex64 { network: Any, index: 23 }; diff --git a/xcm/src/v1/multilocation.rs b/xcm/src/v1/multilocation.rs index 0c2b2da31698..83cf0095c3b8 100644 --- a/xcm/src/v1/multilocation.rs +++ b/xcm/src/v1/multilocation.rs @@ -253,6 +253,24 @@ impl MultiLocation { self.interior.match_and_split(&prefix.interior) } + /// Returns whether `self` has the same number of parents as `prefix` and its junctions begins + /// with the junctions of `prefix`. + /// + /// # Example + /// ```rust + /// # use xcm::v1::{Junctions::*, Junction::*, MultiLocation}; + /// let m = MultiLocation::new(1, X3(PalletInstance(3), OnlyChild, OnlyChild)); + /// assert!(m.starts_with(&MultiLocation::new(1, X1(PalletInstance(3))))); + /// assert!(!m.starts_with(&MultiLocation::new(1, X1(GeneralIndex(99))))); + /// assert!(!m.starts_with(&MultiLocation::new(0, X1(PalletInstance(3))))); + /// ``` + pub fn starts_with(&self, prefix: &MultiLocation) -> bool { + if self.parents != prefix.parents { + return false + } + self.interior.starts_with(&prefix.interior) + } + /// Mutate `self` so that it is suffixed with `suffix`. /// /// Does not modify `self` and returns `Err` with `suffix` in case of overflow. @@ -801,15 +819,29 @@ impl Junctions { /// # } /// ``` pub fn match_and_split(&self, prefix: &Junctions) -> Option<&Junction> { - if prefix.len() + 1 != self.len() { + if prefix.len() + 1 != self.len() || !self.starts_with(prefix) { return None } - for i in 0..prefix.len() { - if prefix.at(i) != self.at(i) { - return None - } + self.at(prefix.len()) + } + + /// Returns whether `self` begins with or is equal to `prefix`. + /// + /// # Example + /// ```rust + /// # use xcm::v1::{Junctions::*, Junction::*}; + /// let mut j = X3(Parachain(2), PalletInstance(3), OnlyChild); + /// assert!(j.starts_with(&X2(Parachain(2), PalletInstance(3)))); + /// assert!(j.starts_with(&j)); + /// assert!(j.starts_with(&X1(Parachain(2)))); + /// assert!(!j.starts_with(&X1(Parachain(999)))); + /// assert!(!j.starts_with(&X4(Parachain(2), PalletInstance(3), OnlyChild, OnlyChild))); + /// ``` + pub fn starts_with(&self, prefix: &Junctions) -> bool { + if self.len() < prefix.len() { + return false } - return self.at(prefix.len()) + prefix.iter().zip(self.iter()).all(|(l, r)| l == r) } } @@ -929,6 +961,26 @@ mod tests { assert_eq!(m.match_and_split(&m), None); } + #[test] + fn starts_with_works() { + let full: MultiLocation = + (Parent, Parachain(1000), AccountId32 { network: Any, id: [0; 32] }).into(); + let identity: MultiLocation = full.clone(); + let prefix: MultiLocation = (Parent, Parachain(1000)).into(); + let wrong_parachain: MultiLocation = (Parent, Parachain(1001)).into(); + let wrong_account: MultiLocation = + (Parent, Parachain(1000), AccountId32 { network: Any, id: [1; 32] }).into(); + let no_parents: MultiLocation = (Parachain(1000)).into(); + let too_many_parents: MultiLocation = (Parent, Parent, Parachain(1000)).into(); + + assert!(full.starts_with(&identity)); + assert!(full.starts_with(&prefix)); + assert!(!full.starts_with(&wrong_parachain)); + assert!(!full.starts_with(&wrong_account)); + assert!(!full.starts_with(&no_parents)); + assert!(!full.starts_with(&too_many_parents)); + } + #[test] fn append_with_works() { let acc = AccountIndex64 { network: Any, index: 23 }; diff --git a/xcm/xcm-builder/Cargo.toml b/xcm/xcm-builder/Cargo.toml index d2858ca19de2..a1e7b272933c 100644 --- a/xcm/xcm-builder/Cargo.toml +++ b/xcm/xcm-builder/Cargo.toml @@ -1,30 +1,30 @@ [package] -authors = ["Parity Technologies "] -edition = "2021" name = "xcm-builder" description = "Tools & types for building with XCM and its executor." -version = "0.9.31" +authors.workspace = true +edition.workspace = true +version.workspace = true [dependencies] parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } xcm = { path = "..", default-features = false } xcm-executor = { path = "../xcm-executor", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } log = { version = "0.4.17", default-features = false } # Polkadot dependencies polkadot-parachain = { path = "../../parachain", default-features = false } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } pallet-xcm = { path = "../pallet-xcm" } polkadot-runtime-parachains = { path = "../../runtime/parachains" } [features] diff --git a/xcm/xcm-builder/src/currency_adapter.rs b/xcm/xcm-builder/src/currency_adapter.rs index 5e259195c4a0..f231bf1094b4 100644 --- a/xcm/xcm-builder/src/currency_adapter.rs +++ b/xcm/xcm-builder/src/currency_adapter.rs @@ -125,6 +125,9 @@ impl< AllowDeath, ) .is_ok(); + if ok { + Currency::reactivate(amount); + } debug_assert!( ok, "`can_check_in` must have returned `true` immediately prior; qed" @@ -138,6 +141,7 @@ impl< if let Some(amount) = Matcher::matches_fungible(what) { if let Some(checked_account) = CheckedAccount::get() { Currency::deposit_creating(&checked_account, amount); + Currency::deactivate(amount); } } } diff --git a/xcm/xcm-builder/src/tests.rs b/xcm/xcm-builder/src/tests.rs index fe3f144e95c9..d26a2f008884 100644 --- a/xcm/xcm-builder/src/tests.rs +++ b/xcm/xcm-builder/src/tests.rs @@ -15,7 +15,7 @@ // along with Polkadot. If not, see . use super::{mock::*, test_utils::*, *}; -use frame_support::{assert_err, weights::constants::WEIGHT_PER_SECOND}; +use frame_support::{assert_err, weights::constants::WEIGHT_REF_TIME_PER_SECOND}; use xcm::latest::prelude::*; use xcm_executor::{traits::*, Config, XcmExecutor}; @@ -676,8 +676,8 @@ fn weight_trader_tuple_should_work() { pub const PARA_2: MultiLocation = X1(Parachain(2)).into(); parameter_types! { - pub static HereWeightPrice: (AssetId, u128) = (Here.into().into(), WEIGHT_PER_SECOND.ref_time().into()); - pub static PARA1WeightPrice: (AssetId, u128) = (PARA_1.into(), WEIGHT_PER_SECOND.ref_time().into()); + pub static HereWeightPrice: (AssetId, u128) = (Here.into().into(), WEIGHT_REF_TIME_PER_SECOND.into()); + pub static PARA1WeightPrice: (AssetId, u128) = (PARA_1.into(), WEIGHT_REF_TIME_PER_SECOND.into()); } type Traders = ( diff --git a/xcm/xcm-builder/src/weight.rs b/xcm/xcm-builder/src/weight.rs index 2a86f30d632b..2ab8afde2da5 100644 --- a/xcm/xcm-builder/src/weight.rs +++ b/xcm/xcm-builder/src/weight.rs @@ -17,7 +17,7 @@ use frame_support::{ dispatch::GetDispatchInfo, traits::{tokens::currency::Currency as CurrencyT, Get, OnUnbalanced as OnUnbalancedT}, - weights::{constants::WEIGHT_PER_SECOND, WeightToFee as WeightToFeeT}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, WeightToFee as WeightToFeeT}, }; use parity_scale_codec::Decode; use sp_runtime::traits::{SaturatedConversion, Saturating, Zero}; @@ -153,7 +153,7 @@ impl, R: TakeRevenue> WeightTrader weight, payment, ); let (id, units_per_second) = T::get(); - let amount = units_per_second * (weight as u128) / (WEIGHT_PER_SECOND.ref_time() as u128); + let amount = units_per_second * (weight as u128) / (WEIGHT_REF_TIME_PER_SECOND as u128); let unused = payment.checked_sub((id, amount).into()).map_err(|_| XcmError::TooExpensive)?; self.0 = self.0.saturating_add(weight); @@ -165,7 +165,7 @@ impl, R: TakeRevenue> WeightTrader log::trace!(target: "xcm::weight", "FixedRateOfConcreteFungible::refund_weight weight: {:?}", weight); let (id, units_per_second) = T::get(); let weight = weight.min(self.0); - let amount = units_per_second * (weight as u128) / (WEIGHT_PER_SECOND.ref_time() as u128); + let amount = units_per_second * (weight as u128) / (WEIGHT_REF_TIME_PER_SECOND as u128); self.0 -= weight; self.1 = self.1.saturating_sub(amount); if amount > 0 { @@ -205,7 +205,7 @@ impl, R: TakeRevenue> WeightTrader for FixedRateOfFungib weight, payment, ); let (id, units_per_second) = T::get(); - let amount = units_per_second * (weight as u128) / (WEIGHT_PER_SECOND.ref_time() as u128); + let amount = units_per_second * (weight as u128) / (WEIGHT_REF_TIME_PER_SECOND as u128); if amount == 0 { return Ok(payment) } @@ -220,7 +220,7 @@ impl, R: TakeRevenue> WeightTrader for FixedRateOfFungib log::trace!(target: "xcm::weight", "FixedRateOfFungible::refund_weight weight: {:?}", weight); let (id, units_per_second) = T::get(); let weight = weight.min(self.0); - let amount = units_per_second * (weight as u128) / (WEIGHT_PER_SECOND.ref_time() as u128); + let amount = units_per_second * (weight as u128) / (WEIGHT_REF_TIME_PER_SECOND as u128); self.0 -= weight; self.1 = self.1.saturating_sub(amount); if amount > 0 { diff --git a/xcm/xcm-executor/Cargo.toml b/xcm/xcm-executor/Cargo.toml index 134d4f06947c..f5083eda084f 100644 --- a/xcm/xcm-executor/Cargo.toml +++ b/xcm/xcm-executor/Cargo.toml @@ -1,22 +1,22 @@ [package] -authors = ["Parity Technologies "] -edition = "2021" name = "xcm-executor" description = "An abstract and configurable XCM message executor." -version = "0.9.31" +authors.workspace = true +edition.workspace = true +version.workspace = true [dependencies] impl-trait-for-tuples = "0.2.2" parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } xcm = { path = "..", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } log = { version = "0.4.17", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.31" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true , branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/xcm/xcm-executor/integration-tests/Cargo.toml b/xcm/xcm-executor/integration-tests/Cargo.toml index ddb38f41922e..efd2146a7bfc 100644 --- a/xcm/xcm-executor/integration-tests/Cargo.toml +++ b/xcm/xcm-executor/integration-tests/Cargo.toml @@ -1,25 +1,25 @@ [package] -authors = ["Parity Technologies "] -edition = "2021" name = "xcm-executor-integration-tests" description = "Integration tests for the XCM Executor" -version = "0.9.31" +authors.workspace = true +edition.workspace = true +version.workspace = true [dependencies] -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } futures = "0.3.21" 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" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.31" } -sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "polkadot-v0.9.36" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } xcm = { path = "../..", default-features = false } xcm-executor = { path = ".." } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } [features] default = ["std"] diff --git a/xcm/xcm-executor/integration-tests/src/lib.rs b/xcm/xcm-executor/integration-tests/src/lib.rs index 821987531aa0..f038e45d3edc 100644 --- a/xcm/xcm-executor/integration-tests/src/lib.rs +++ b/xcm/xcm-executor/integration-tests/src/lib.rs @@ -60,7 +60,7 @@ fn basic_buy_fees_message_executes() { 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(|| { + 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( @@ -101,7 +101,7 @@ fn query_response_fires() { .expect("imports the block"); let mut query_id = None; - client.state_at(&block_hash).expect("state should exist").inspect_state(|| { + client.state_at(block_hash).expect("state should exist").inspect_state(|| { for r in polkadot_test_runtime::System::events().iter() { match r.event { TestNotifier(QueryPrepared(q)) => query_id = Some(q), @@ -136,7 +136,7 @@ fn query_response_fires() { 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(|| { + 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::ResponseReady( @@ -184,7 +184,7 @@ fn query_response_elicits_handler() { .expect("imports the block"); let mut query_id = None; - client.state_at(&block_hash).expect("state should exist").inspect_state(|| { + client.state_at(block_hash).expect("state should exist").inspect_state(|| { for r in polkadot_test_runtime::System::events().iter() { match r.event { TestNotifier(NotifyQueryPrepared(q)) => query_id = Some(q), @@ -218,7 +218,7 @@ fn query_response_elicits_handler() { 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(|| { + client.state_at(block_hash).expect("state should exist").inspect_state(|| { assert!(polkadot_test_runtime::System::events().iter().any(|r| matches!( r.event, TestNotifier(ResponseReceived( diff --git a/xcm/xcm-executor/src/assets.rs b/xcm/xcm-executor/src/assets.rs index 324e92dce9ff..6ecbf0e0cf44 100644 --- a/xcm/xcm-executor/src/assets.rs +++ b/xcm/xcm-executor/src/assets.rs @@ -100,14 +100,14 @@ impl Assets { } /// A borrowing iterator over the fungible assets. - pub fn fungible_assets_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn fungible_assets_iter(&self) -> impl Iterator + '_ { self.fungible .iter() .map(|(id, &amount)| MultiAsset { fun: Fungible(amount), id: id.clone() }) } /// A borrowing iterator over the non-fungible assets. - pub fn non_fungible_assets_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn non_fungible_assets_iter(&self) -> impl Iterator + '_ { self.non_fungible .iter() .map(|(id, instance)| MultiAsset { fun: NonFungible(instance.clone()), id: id.clone() }) @@ -126,7 +126,7 @@ impl Assets { } /// A borrowing iterator over all assets. - pub fn assets_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn assets_iter(&self) -> impl Iterator + '_ { self.fungible_assets_iter().chain(self.non_fungible_assets_iter()) } diff --git a/xcm/xcm-simulator/Cargo.toml b/xcm/xcm-simulator/Cargo.toml index 569d301ece94..d680e8849f0f 100644 --- a/xcm/xcm-simulator/Cargo.toml +++ b/xcm/xcm-simulator/Cargo.toml @@ -1,17 +1,17 @@ [package] name = "xcm-simulator" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Test kit to simulate cross-chain message passing and XCM execution" -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } paste = "1.0.7" -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } xcm = { path = "../" } xcm-executor = { path = "../xcm-executor" } diff --git a/xcm/xcm-simulator/example/Cargo.toml b/xcm/xcm-simulator/example/Cargo.toml index 8725673eda79..8e1ee791f39e 100644 --- a/xcm/xcm-simulator/example/Cargo.toml +++ b/xcm/xcm-simulator/example/Cargo.toml @@ -1,21 +1,21 @@ [package] name = "xcm-simulator-example" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Examples of xcm-simulator usage." -edition = "2021" +authors.workspace = true +edition.workspace = true +version.workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } scale-info = { version = "2.1.2", features = ["derive"] } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } xcm = { path = "../../" } xcm-simulator = { path = "../" } diff --git a/xcm/xcm-simulator/example/src/parachain.rs b/xcm/xcm-simulator/example/src/parachain.rs index ff435a9238fd..d638867c281f 100644 --- a/xcm/xcm-simulator/example/src/parachain.rs +++ b/xcm/xcm-simulator/example/src/parachain.rs @@ -20,7 +20,7 @@ use codec::{Decode, Encode}; use frame_support::{ construct_runtime, parameter_types, traits::{Everything, Nothing}, - weights::{constants::WEIGHT_PER_SECOND, Weight}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, }; use sp_core::H256; use sp_runtime::{ @@ -97,8 +97,8 @@ impl pallet_balances::Config for Runtime { } parameter_types! { - pub const ReservedXcmpWeight: Weight = WEIGHT_PER_SECOND.saturating_div(4); - pub const ReservedDmpWeight: Weight = WEIGHT_PER_SECOND.saturating_div(4); + pub const ReservedXcmpWeight: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4)); + pub const ReservedDmpWeight: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4)); } parameter_types! { diff --git a/xcm/xcm-simulator/fuzzer/Cargo.toml b/xcm/xcm-simulator/fuzzer/Cargo.toml index 3137db72ff0b..012b146115b2 100644 --- a/xcm/xcm-simulator/fuzzer/Cargo.toml +++ b/xcm/xcm-simulator/fuzzer/Cargo.toml @@ -1,22 +1,22 @@ [package] name = "xcm-simulator-fuzzer" -version = "0.9.31" -authors = ["Parity Technologies "] description = "Examples of xcm-simulator usage." -edition = "2021" +version.workspace = true +authors.workspace = true +edition.workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } honggfuzz = "0.5.55" scale-info = { version = "2.1.2", features = ["derive"] } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.31" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.36" } xcm = { path = "../../" } xcm-simulator = { path = "../" } diff --git a/xcm/xcm-simulator/fuzzer/src/parachain.rs b/xcm/xcm-simulator/fuzzer/src/parachain.rs index b8b51e57e853..ce2a2698d00c 100644 --- a/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -20,7 +20,7 @@ use codec::{Decode, Encode}; use frame_support::{ construct_runtime, parameter_types, traits::{Everything, Nothing}, - weights::{constants::WEIGHT_PER_SECOND, Weight}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, }; use sp_core::H256; use sp_runtime::{ @@ -97,8 +97,8 @@ impl pallet_balances::Config for Runtime { } parameter_types! { - pub const ReservedXcmpWeight: Weight = WEIGHT_PER_SECOND.saturating_div(4); - pub const ReservedDmpWeight: Weight = WEIGHT_PER_SECOND.saturating_div(4); + pub const ReservedXcmpWeight: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4)); + pub const ReservedDmpWeight: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND.saturating_div(4)); } parameter_types! { diff --git a/xcm/xcm-simulator/src/lib.rs b/xcm/xcm-simulator/src/lib.rs index 69a8e088a0da..a8d602037cd5 100644 --- a/xcm/xcm-simulator/src/lib.rs +++ b/xcm/xcm-simulator/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 . -//! Test kit to simulate cross-chain message passing and XCM execution +//! Test kit to simulate cross-chain message passing and XCM execution. pub use codec::Encode; pub use paste; @@ -62,6 +62,7 @@ pub enum MessageKind { Xcmp, } +/// Encodes the provided XCM message based on the `message_kind`. pub fn encode_xcm(message: Xcm<()>, message_kind: MessageKind) -> Vec { match message_kind { MessageKind::Ump | MessageKind::Dmp => VersionedXcm::<()>::from(message).encode(), @@ -76,6 +77,19 @@ pub fn encode_xcm(message: Xcm<()>, message_kind: MessageKind) -> Vec { } } +/// The macro is implementing upward message passing(UMP) for the provided relay +/// chain struct. The struct has to provide the XCM configuration for the relay +/// chain. +/// +/// ```ignore +/// decl_test_relay_chain! { +/// pub struct Relay { +/// Runtime = relay_chain::Runtime, +/// XcmConfig = relay_chain::XcmConfig, +/// new_ext = relay_ext(), +/// } +/// } +/// ``` #[macro_export] #[rustfmt::skip] macro_rules! decl_test_relay_chain { @@ -108,6 +122,21 @@ macro_rules! decl_test_relay_chain { }; } +/// The macro is implementing the `XcmMessageHandlerT` and `DmpMessageHandlerT` +/// traits for the provided parachain struct. Expects the provided parachain +/// struct to define the XcmpMessageHandler and DmpMessageHandler pallets that +/// contain the message handling logic. +/// +/// ```ignore +/// decl_test_parachain! { +/// pub struct ParaA { +/// Runtime = parachain::Runtime, +/// XcmpMessageHandler = parachain::MsgQueue, +/// DmpMessageHandler = parachain::MsgQueue, +/// new_ext = para_ext(), +/// } +/// } +/// ``` #[macro_export] macro_rules! decl_test_parachain { ( @@ -153,6 +182,7 @@ macro_rules! decl_test_parachain { }; } +/// Implements the `TestExt` trait for a specified struct. #[macro_export] macro_rules! __impl_ext { // entry point: generate ext name @@ -202,6 +232,23 @@ thread_local! { = RefCell::new(VecDeque::new()); } +/// Declares a test network that consists of a relay chain and multiple +/// parachains. Expects a network struct as an argument and implements testing +/// functionality, `ParachainXcmRouter` and the `RelayChainXcmRouter`. The +/// struct needs to contain the relay chain struct and an indexed list of +/// parachains that are going to be in the network. +/// +/// ```ignore +/// decl_test_network! { +/// pub struct ExampleNet { +/// relay_chain = Relay, +/// parachains = vec![ +/// (1, ParaA), +/// (2, ParaB), +/// ], +/// } +/// } +/// ``` #[macro_export] macro_rules! decl_test_network { ( @@ -215,16 +262,16 @@ macro_rules! decl_test_network { impl $name { pub fn reset() { use $crate::{TestExt, VecDeque}; - // Reset relay chain message bus + // Reset relay chain message bus. $crate::RELAY_MESSAGE_BUS.with(|b| b.replace(VecDeque::new())); - // Reset parachain message bus + // Reset parachain message bus. $crate::PARA_MESSAGE_BUS.with(|b| b.replace(VecDeque::new())); <$relay_chain>::reset_ext(); $( <$parachain>::reset_ext(); )* } } - /// Check if any messages exist in either message bus + /// Check if any messages exist in either message bus. fn exists_messages_in_any_bus() -> bool { use $crate::{RELAY_MESSAGE_BUS, PARA_MESSAGE_BUS}; let no_relay_messages_left = RELAY_MESSAGE_BUS.with(|b| b.borrow().is_empty());